2015-11-02 66 views
1

這裏這種緩慢的查詢是我的查詢,如何優化與多個AND和OR

SELECT transaktion.betrag_eur 
FROM transaktion_buchung AS transaktion 
WHERE transaktion.fk_kunde=303276 
    AND transaktion.konto='Cashback' 
    AND transaktion.storniert_am IS NULL 
    AND transaktion.freigegeben_am IS NULL 
    AND (transaktion.buchungstyp!='Zahlung' OR transaktion.buchungstyp IS NULL) 

我得到不正確的密鑰文件錯誤此查詢由於磁盤空間的限制。我該如何優化這個查詢?

並解釋該查詢顯示此,

id select_type table type possible_keys key key_len ref rows Extra 
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 653631 Using where 
2 DERIVED transaktion ALL NULL NULL NULL NULL 428809 
2 DERIVED buchung ref fk_buchung_transaktion fk_buchung_transaktion 5 card4students.transaktion.id 1 Using where; Not exists 
2 DERIVED filiale eq_ref PRIMARY PRIMARY 4 card4students.transaktion.fk_filiale 1 
3 UNION buchung ref konto konto 1  337602 Using where 
3 UNION transaktion eq_ref PRIMARY PRIMARY 4 card4students.buchung.fk_transaktion 1 
3 UNION filiale eq_ref PRIMARY PRIMARY 4 card4students.transaktion.fk_filiale 1 
3 UNION auszahlung eq_ref PRIMARY PRIMARY 4 card4students.buchung.fk_auszahlung 1 
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL  

在這種情況下,transaktion_buchung是一個視圖。

架構爲transaktion_buchung:

CREATE 
    ALGORITHM = UNDEFINED 
    DEFINER = `db_card4students`@`%` 
    SQL SECURITY DEFINER VIEW `transaktion_buchung` AS 
(
SELECT 
     `transaktion`.`fk_kunde` AS `fk_kunde`, 
     `transaktion`.`id` AS `fk_transaktion`, 
     `buchung`.`id` AS `fk_buchung`, 
     NULL AS `auszahlung_gewuenscht`, 
     `transaktion`.`betrag_eur` AS `betrag_eur`, 
     `transaktion`.`nettoumsatz` AS `nettoumsatz`, 
     `transaktion`.`mwst` AS `mwst`, 
     NULL AS `fk_abrechnung`, 
     `filiale`.`name` AS `filiale_name`, 
     `transaktion`.`storniert_am` AS `storniert_am`, 
     `transaktion`.`freigegeben_am` AS `freigegeben_am`, 
     `buchung`.`buchungstyp` AS `buchungstyp`, 
     `transaktion`.`konto` AS `konto`, 
     0 AS `auszahlung_vorgenommen`, 
     `transaktion`.`recordbirthdate` AS `recordbirthdate` 
    FROM 
     ((`transaktion` 
     LEFT JOIN `buchung` ON ((`buchung`.`fk_transaktion` = `transaktion`.`id`))) 
     LEFT JOIN `filiale` ON ((`filiale`.`id` = `transaktion`.`fk_filiale`))) 
    WHERE 
     ISNULL(`buchung`.`id`) 
) UNION ALL (
SELECT 
     `buchung`.`fk_kunde` AS `fk_kunde`, 
     `buchung`.`fk_transaktion` AS `fk_transaktion`, 
     `buchung`.`id` AS `fk_buchung`, 
     `buchung`.`auszahlung_gewuenscht` AS `auszahlung_gewuenscht`, 
     `buchung`.`betrag_eur` AS `betrag_eur`, 
     `transaktion`.`nettoumsatz` AS `nettoumsatz`, 
     `transaktion`.`mwst` AS `mwst`, 
     `auszahlung`.`fk_abrechnung` AS `fk_abrechnung`, 
     `filiale`.`name` AS `filiale_name`, 
     `transaktion`.`storniert_am` AS `storniert_am`, 
     IF(ISNULL(`transaktion`.`id`), 
      NOW(), 
      `transaktion`.`freigegeben_am`) AS `freigegeben_am`, 
     `buchung`.`buchungstyp` AS `buchungstyp`, 
     `buchung`.`konto` AS `konto`, 
     `buchung`.`auszahlung_vorgenommen` AS `auszahlung_vorgenommen`, 
     IF((`transaktion`.`recordbirthdate` IS NOT NULL), 
      `transaktion`.`recordbirthdate`, 
      `buchung`.`recordbirthdate`) AS `recordbirthdate` 
    FROM 
     (((`buchung` 
     LEFT JOIN `transaktion` ON ((`transaktion`.`id` = `buchung`.`fk_transaktion`))) 
     LEFT JOIN `filiale` ON ((`filiale`.`id` = `transaktion`.`fk_filiale`))) 
     LEFT JOIN `auszahlung` ON ((`auszahlung`.`id` = `buchung`.`fk_auszahlung`))) 
    WHERE 
     (`buchung`.`konto` = _UTF8'Cashback') 
) 
+0

1)購買更大的盒子2)將索引添加到'transaktion_buchung'表 – lad2025

+0

發佈您的'transaktion_buchung'模式 – Alex

+0

有沒有人問你「EXPLAIN」? – Alex

回答

0

優化這個查詢,你只需要一個綜合指數:

create index idx_transaktion_buchung on 
    transaktion_buchung(fk_kunde, konto, stonriert, freigegeben_am, buchungstyp, betrag_eur); 

這是用於查詢的覆蓋索引,所以應該是比較快的。

+0

是否需要將'betrag_eur'放入索引中? – Alex

+0

'stonriert'應該是'stonriert_am'? – Alex

+0

transaktion_buchung是一個視圖。我在問題詳細信息中添加了相關模式 –

0

我懷疑MySQL沒有使用任何非常有用的索引。它可能會返回一個非常大的結果集(使用連接的索引),但隨後將掃描每個返回的行以檢查您在WHERE子句中查找的值。

因此,可能值得在不使用視圖的情況下編寫查詢。像這樣的東西我認爲: -

SELECT transaktion.fk_kunde AS fk_kunde, 
    transaktion.id AS fk_transaktion, 
    buchung.id AS fk_buchung, 
    NULL AS auszahlung_gewuenscht, 
    transaktion.betrag_eur AS betrag_eur, 
    transaktion.nettoumsatz AS nettoumsatz, 
    transaktion.mwst AS mwst, 
    NULL AS fk_abrechnung, 
    filiale.name AS filiale_name, 
    transaktion.storniert_am AS storniert_am, 
    transaktion.freigegeben_am AS freigegeben_am, 
    buchung.buchungstyp AS buchungstyp, 
    transaktion.konto AS konto, 
    0 AS auszahlung_vorgenommen, 
    transaktion.recordbirthdate AS recordbirthdate 
FROM transaktion 
LEFT JOIN buchung ON buchung.fk_transaktion = transaktion.id 
LEFT JOIN filiale ON filiale.id = transaktion.fk_filiale 
WHERE ISNULL(buchung.id) 
AND transaktion.fk_kunde=303276 
AND transaktion.konto='Cashback' 
AND transaktion.storniert_am IS NULL 
AND transaktion.freigegeben_am IS NULL 
AND (transaktion.buchungstyp!='Zahlung' 
OR transaktion.buchungstyp IS NULL) 
UNION ALL 
SELECT buchung.fk_kunde AS fk_kunde, 
    buchung.fk_transaktion AS fk_transaktion, 
    buchung.id AS fk_buchung, 
    buchung.auszahlung_gewuenscht AS auszahlung_gewuenscht, 
    buchung.betrag_eur AS betrag_eur, 
    transaktion.nettoumsatz AS nettoumsatz, 
    transaktion.mwst AS mwst, 
    auszahlung.fk_abrechnung AS fk_abrechnung, 
    filiale.name AS filiale_name, 
    transaktion.storniert_am AS storniert_am, 
    IF(ISNULL(transaktion.id), NOW(), transaktion.freigegeben_am) AS freigegeben_am, 
    buchung.buchungstyp AS buchungstyp, 
    buchung.konto AS konto, 
    buchung.auszahlung_vorgenommen AS auszahlung_vorgenommen, 
    IF((transaktion.recordbirthdate IS NOT NULL), 
    transaktion.recordbirthdate, buchung.recordbirthdate) AS recordbirthdate 
FROM buchung 
LEFT JOIN transaktion ON transaktion.id = buchung.fk_transaktion 
LEFT JOIN filiale ON filiale.id = transaktion.fk_filiale 
LEFT JOIN auszahlung ON auszahlung.id = buchung.fk_auszahlung 
WHERE buchung.konto = _UTF8'Cashback' 
AND buchung.fk_kunde=303276 
AND transaktion.storniert_am IS NULL 
AND transaktion.freigegeben_am IS NULL 
AND transaktion.id IS NOT NULL 
AND transaktion.freigegeben_am IS NULL 
AND (buchung.buchungstyp!='Zahlung' 
OR buchung.buchungstyp IS NULL) 

您可能需要buchung涵蓋fk_kunde和konto的複合索引。並在transaktion涵蓋fk_kunde和konto的複合指數。