10

説明に関連する基本的な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
4

2 に答える 2

4

実際、あなたが見るとき、あなたは掛け算するべきではなく、この数を合計するべきです。あなたの場合、(49520 x 413 x 4)と(50000 + 49520)を比較してください。

一般的なルールは単純です。すべてのセグメント(派生、プライマリ)を要約し、各セグメント内の行を乗算します。

id select_type  ... rows
1  PRIMARY           1
1  PRIMARY           2
2  DERIVED           3
2  DERIVED           4
3  DERIVED           5
3  DERIVED           6

複雑さは次のとおりです:1 * 2 + 3 * 4 + 5 * 6

于 2013-05-16T19:07:10.300 に答える
0

EXPLAINの「行」ステートメントにあまり信頼を置かないでください。mysqlのドキュメントのように:「調査する行の見積もり」(http://dev.mysql.com/doc/refman/5.1/en/explain-output.html)。

おそらく、インデックス統計を更新すると、より適切な見積もりが得られます(OPTIMIZE TABLE、http://dev.mysql.com/doc/refman/5.0/en/optimize-table.html

于 2013-04-28T10:09:10.940 に答える