説明に関連する基本的なMySQLパフォーマンスの質問があります。EXPLAIN
同じ結果を返す2つのクエリがあり、実行プランの意味を理解する方法を理解しようとしています。
テーブルには50000レコードがあり、レコード比較を実行しています。私の最初のクエリの実行には18.625秒かかります。説明プランは以下の通りです。
id select_type table type possible_keys key key_len ref rows filtered Extra
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
1 SIMPLE a ALL NULL NULL NULL NULL 49520 100.00
1 SIMPLE b ref scoreEvent,eventScore eventScore 4 olympics.a.eventId 413 100.00 Using where; Using index; Not exists
1 SIMPLE c ref PRIMARY,scoreEvent,eventScore scoreEvent 8 olympics.a.score,olympics.a.eventId 4 100.00 Using where; Using index; Not exists
次のクエリの実行には0.106秒かかります...
id select_type table type possible_keys key key_len ref rows filtered Extra
-----------------------------------------------------------------------------------------------------------------------------------
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 50000 100.00 Using temporary; Using filesort
2 DERIVED results ALL NULL NULL NULL NULL 49520 100.00 Using filesort
ドキュメントではALL
、全表スキャンが必要であり、これは非常に悪いと書かれています。またfilesort
、レコードを並べ替えるには追加のパスが必要であると述べています。また、 MySQLが最適化Not exists
を実行できたことを意味します。LEFT JOIN
また、最初の方法ではインデックスを使用しているのに対し、2番目の方法では使用していないことも明らかです。
私はここで何が起こっているのか、そしてどのような数学が関係しているのかを解明しようとしています。私はRESET QUERY CACHE
テストの合間に実行して、不当なアドバンテージが与えられていないことを確認しています。49520 x 413 x 4は、50000x49520よりもはるかに小さいです。
id
説明計画のと関係がありますか?
これらのクエリや他のクエリをテストしているとき、同じIDのアイテムを乗算し、各IDの結果を合計することで、クエリの複雑さを概算できるようです...これは有効な仮定ですか?
追加
コメントで要求されたように、それが役立つ場合に備えてスキーマとクエリがありますが、私はより良いクエリを探していません...単なる説明ですEXPLAIN
。問題のテーブル...
CREATE TABLE results (
resultId INT NOT NULL auto_increment KEY,
athleteId INT NOT NULL,
eventId INT NOT NULL,
score INT NOT NULL,
CONSTRAINT FOREIGN KEY (athleteId) REFERENCES athletes(athleteId),
CONSTRAINT FOREIGN KEY (eventId) REFERENCES events(eventId),
INDEX eventScore (eventId, score),
INDEX scoreEvent (score, eventId)
) ENGINE=innodb;
最初のクエリ...
SELECT a.resultId, a.eventId, a.athleteId, a.score
FROM results a
-- Find records with matching eventIds and greater scores
LEFT JOIN results b
ON b.eventId = a.eventId
AND b.score > a.score
-- Find records with matching scores and lesser testIds
LEFT JOIN results c
ON c.eventId = a.eventId
AND c.score = a.score
AND c.resultId < a.resultId
-- Filter out all records where there were joins
WHERE c.resultId IS NULL
AND b.resultId IS NULL;
2番目のクエリ...
SELECT resultId, athleteId, eventId, score
FROM (
SELECT resultId, athleteId, eventId, score
FROM results
ORDER BY eventId, score DESC, resultId
) AS a
GROUP BY eventId;
また、インデックスを削除するeventScore
と、クエリが2.531秒に低下し、実行プランはそれほど変更されませんが、possible_keysの順序が変更されUsing index
、テーブル用ではないことに気付きましたb
(生成している行数のわずかな変更は無視してください)スキーマを変更するたびにデータ)...
id select_type table type possible_keys key key_len ref rows filtered Extra
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
1 SIMPLE a ALL NULL NULL NULL NULL 47457 100.00
1 SIMPLE b ref eventId,scoreEvent eventId 4 olympics.a.eventId 659 100.00 Using where; Not exists
1 SIMPLE c ref PRIMARY,eventId,scoreEvent scoreEvent 8 olympics.a.score,olympics.a.eventId 5 100.00 Using where; Using index; Not exists