と範囲を使用して、MySQLのテーブルは、以下の2つのテーブルのテーブル(簡略化)を含む:各package_id
/for_date
複合キー
(~13000) (~7000000 rows)
--------------- --------------------
| packages | | packages_prices |
--------------- --------------------
| id (int) |<- ->| package_id (int) |
| state (int) | | variant_id (int) |
- - - - - - - | for_date (date) |
| price (float) |
- - - - - - - - -
の組合せはわずか数(平均3)変種有します。 state
は0(非アクティブ)または1(アクティブ)です。 13000人のうち4000人がアクティブです。
まず私はちょうど価格セット(関係なく、変動の)を持っているパッケージを知りたいので、私は(1)for_date
をカバーする複合キーを追加し、(2)pid
と私は照会:
select distinct package_id from packages_prices where for_date > date(now())
このクエリは3500行を返すのに1秒かかりますが、これは多すぎます。 Explainは複合キーがkey_len 3と一緒に使用され、2000000行が100%フィルタリングされて型範囲で検査されることを示しています。 Using where; Using index; Using temporary
。この区別は3500行に戻ります。
distinct
を取り除くと、Using temporary
は言及されなくなりますが、クエリは1000000行を返しますが、依然として1秒かかります。
質問1:なぜ、このクエリは非常に遅く、私はテーブルの列を追加または変更することなく、それをどのようにスピードアップできますか?コンポジットキーを考えると、このクエリのコストは0,01未満になるはずです。
今私はアクティブの価格が設定されているパッケージを知りたいと思っています。
私はstate
にキーを追加し、上記のように逆の順序で新しい複合キーを追加します。
select distinct packages.id from packages
inner join packages_prices on id = package_id and for_date > date(now())
where state = 1
クエリには2秒かかります。説明はpackages
テーブルについて教えてください。state
のキーはkey_len 4で使用され、4000行が検査され、100%タイプのタイプrefがフィルタされます。 Using index; Using temporary
。 packages_prices
テーブルでは、新しい複合キーがkey_len 4で使用され、1000行が検査され、タイプrefで33.33%のフィルタリングが行われます。 Using where; Using index; Distinct
。差別化はそれを3000行に戻す。
distinct
を取り除くと、Using temporary
とDistinct
にはもう言及されませんが、クエリは850000行を返し、3秒かかります。
質問2:なぜクエリがそれほど遅いのですか? Explainに基づいて範囲が使用されなくなったのはなぜですか?なぜ新しいコンポジットキーを使用したフィルタリングが33.33%に下がったのですか?私はコンポジットキーが再び100%予兆をフィルタリングすることを期待していました。
これはすべて基本的で些細なようですが、時間がかかり、時間がかかりましたが、実際に何が起こっているのかまだ分かりません。
まず、2つに分けて質問してください。それから、テーブルの作成、索引の作成、完全な説明計画の表示をしてください。 –
あなたが '異形 'と言ったとき、あなたは異なる' packages_prices'を意味しますか? –
@HoneyBadgerこれらは2つの別々のテーブルです。しかし、彼はそれを並べて置く。 –