簡體   English   中英

帶JOINS的MySQL非常慢

[英]MySQL with JOINS is very slow

我有這個查詢:

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行,表“詳細信息”約有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列上添加一個索引。

在詳細信息表上,添加一個覆蓋beschreibungauftrags_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還有多少其他值),但是沒有解決由於不匹配的數據類型更改了索引而導致的問題。索引幾乎肯定沒有幫助。

對於您的查詢,您需要以下索引:

auftrag(erledigt, id)
details(auftrags_id, beschreibung)
kunden(kunde, firma)

您也可以將查詢重寫為條件聚合,但是正確的索引將有很大幫助。

注意:復合索引中列的順序很重要。

在這種情況下,InnoDB將明顯勝過MyISAM。 details ,具有PRIMARY KEY(auftrags_id, beschreibung)

同時,在auftragPRIMARY KEY(id) 戈登(Gordon)推薦的指數是auftragkunden

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM