Mysql 如何使用多个and和OR优化此慢速查询
我的问题是Mysql 如何使用多个and和OR优化此慢速查询,mysql,query-optimization,mysql-workbench,Mysql,Query Optimization,Mysql Workbench,我的问题是 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.
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
要优化此查询,您只需要一个复合索引:
create index idx_transaktion_buchung on
transaktion_buchung(fk_kunde, konto, stonriert, freigegeben_am, buchungstyp, betrag_eur);
这是查询的覆盖索引,因此应该非常快。要优化此查询,您只需要一个复合索引:
create index idx_transaktion_buchung on
transaktion_buchung(fk_kunde, konto, stonriert, freigegeben_am, buchungstyp, betrag_eur);
这是一个用于查询的覆盖索引,因此应该非常快。我怀疑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)
你可能需要一个涵盖fk_kunde和konto的buchung复合索引。在transaktion上,一个包含fk_kunde和konto的复合索引。我怀疑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)
你可能需要一个涵盖fk_kunde和konto的buchung复合索引。在transaktion上,一个包含fk_kunde和konto的复合索引。1)购买更大的框2)将索引添加到
transaktion_buchung
表发布您的transaktion_buchung
方案是否有人向您索要EXPLAIN
?这是同一查询的解释吗?MySQL在使用视图方面非常差。它只是将它们视为子查询,而不使用索引来缩小结果范围。您最好选择用于视图的SELECT并直接使用它(使用上面SELECT中的where子句).1)购买更大的框2)向transaktion\u buchung
表添加索引发布您的transaktion\u buchung
方案是否有人向您索要EXPLAIN
?这是对同一查询的解释吗?MySQL在使用视图方面非常差。它只是将它们视为子查询,而不使用索引来缩小结果范围。您最好选择用于视图的SELECT并直接使用它(使用上述SELECT中的where子句)。是否需要将betrag\u eur
放入索引中?stonriert
应该是stonriert\u am
?transaktion\u buchung是一个视图。我已经在问题细节中添加了相关的模式是否有必要将betrag\u eur
放入索引中?stonriert
应该是stonriert\u am
?transaktion\u buchung是一个视图。我已经在问题细节中添加了相关的模式