这是我的查询,
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)
由于磁盘空间限制,此查询的密钥文件错误不正确。如何优化此查询?
此查询的和EXPLAIN显示此内容,
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 :(得分:0)
要优化此查询,您只需要一个复合索引:
create index idx_transaktion_buchung on
transaktion_buchung(fk_kunde, konto, stonriert, freigegeben_am, buchungstyp, betrag_eur);
这是查询的覆盖索引,因此应该非常快。
答案 1 :(得分: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。