MySQL 使用 JOINS 非常慢

标签 mysql performance

我有这个查询:

select 
b.user as user1, b.timestamp as ts1, 
c.user as user2, c.timestamp as ts2, 
d.user as user3, d.timestamp as ts3,
e.user as user4, e.timestamp as ts4,
f.user as user5, f.timestamp as ts5,
g.user as user6, g.timestamp as ts6,
h.user as user7, h.timestamp as ts7,
i.user as user8, i.timestamp as ts8,
j.user as user9, j.timestamp as ts9,
k.user as user10, k.timestamp as ts10,

a.beschreibung, a.auftragsnummer, a.faellig, a.subkunde,
(SELECT firma from kunden where id=a.kunde limit 0,1) as kunde,
(SELECT kommision from kommision where id=a.kommision limit 0,1) as kommision
 from auftrag a
  left join details b on (b.beschreibung='Step1' AND b.auftrags_id=a.id)
  left join details c on (c.beschreibung='Step2' AND c.auftrags_id=a.id)
  left join details d on (d.beschreibung='Step3' AND d.auftrags_id=a.id)
  left join details e on (e.beschreibung='Step4' AND e.auftrags_id=a.id)
  left join details f on (f.beschreibung='Step5' AND f.auftrags_id=a.id)
  left join details g on (g.beschreibung='Step6' AND g.auftrags_id=a.id)
  left join details h on (h.beschreibung='Step7' AND h.auftrags_id=a.id)
  left join details i on (i.beschreibung='Step8' AND i.auftrags_id=a.id)
  left join details j on (j.beschreibung='Step9' AND j.auftrags_id=a.id)
  left join details k on (k.beschreibung='Step10' AND k.auftrags_id=a.id)



where a.erledigt='1'

它运行得非常非常慢,大约需要 1 分钟才能获得结果集。 表“auftrag”有 820 行,表“details”大约有 7000 行。 我做错了什么?

谢谢 帕特里克

CREATE TABLE auftrag 
( 
    id INT(10) NOT NULL AUTO_INCREMENT, 
    beschreibung VARCHAR(255) NULL DEFAULT '0', 
    auftragsnummer VARCHAR(50) NULL DEFAULT '0', 
    faellig VARCHAR(50) NULL DEFAULT NULL, 
    kunde INT(11) NULL DEFAULT NULL, 
    subkunde VARCHAR(50) NULL DEFAULT NULL, 
    kommision VARCHAR(50) NULL DEFAULT NULL, 
    notiz TEXT NULL, 
    werbeanbringung TEXT NULL, 
    erledigt INT(1) NULL DEFAULT NULL, 
    INDEX Schlüssel 1 (id), 
    INDEX Schlüssel 2 (id, auftragsnummer, kunde, subkunde, beschreibung) 
) COLLATE='latin1_swedish_ci' ENGINE=MyISAM AUTO_INCREMENT=850 ;

CREATE TABLE details 
(   
    id INT(11) NOT NULL AUTO_INCREMENT, 
    auftrags_id VARCHAR(50) NULL DEFAULT '0', 
    beschreibung VARCHAR(50) NULL DEFAULT '0', 
    user VARCHAR(50) NULL DEFAULT '0', 
    timestamp VARCHAR(50) NULL DEFAULT '0', 
    notiz VARCHAR(255) NULL DEFAULT NULL, 
    INDEX Schlüssel 2 (user, timestamp, beschreibung, auftrags_id), 
    INDEX Schlüssel 1 (id, user, timestamp, beschreibung) 
) COLLATE='latin1_swedish_ci' ENGINE=MyISAM AUTO_INCREMENT=7260 ;

最佳答案

您的表上没有对此查询有用的索引,并且您正在将一个表与另一个表重复连接。

在 auftrag 表的 erledigt 列上添加索引。

在详细信息表上添加一个索引,涵盖 beschreibungandauftrags_id

如果您准备稍后处理返回的数据(即,将返回的字段拆分为数组),也可以避免大多数连接。但有点乱:-

SELECT 
    GROUP_CONCAT(CONCAT_WS('##', b.beschreibung, b.user, b.timestamp)),
    a.beschreibung, a.auftragsnummer, a.faellig, a.subkunde,
    (SELECT firma from kunden where id=a.kunde limit 0,1) as kunde,
    (SELECT kommision from kommision where id=a.kommision limit 0,1) as kommision
FROM auftrag a
LEFT OUTER JOIN details b on b.auftrags_id=a.id AND b.beschreibung IN ('Step1', 'Step2', 'Step3', 'Step4', 'Step5', 'Step6', 'Step7', 'Step8', 'Step9', 'Step10')
WHERE a.erledigt='1'
GROUP BY a.id

编辑 - 我刚刚注意到 auftrag 表上的 id 是一个 INT 字段(正如我所期望的),但详细信息表上的 auftrags_id 列是一个 VARCHAR(50) 字段。这将极大地影响性能,因为它需要转换每次比较的值。

请注意,Gordons 上面关于索引字段顺序的评论确实适用(多少取决于实际数据 - 例如有多少个其他 beschreibung 值),但没有解决数据不匹配的问题改变索引的类型几乎肯定不会有帮助。

关于MySQL 使用 JOINS 非常慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32223798/

相关文章:

php - 选择随机数据库行 WHERE ID=由 PHP 函数创建的随机值

Javascript:优化 `reduce` 性能

php - 提高性能、PHP/JSON 解析和 MySQL 编写的建议 - 多个 JSON

mysql - Ruby on Rails 和 MySQL 插入和选择每周事件

php - MySQL 排序未按预期工作

r - 有效地计算一个数据框与另一个数据框的比例

java - 随着需求的增长,如何控制 Hibernate 映射的使用

java - 单线程写入具有不同连接参数的不同数据库

mysql - 尽管加入,但列出所有行

php - 使用php中动态创建的单选按钮的onclick标签更改图像