4

次のようなクエリがあります。

select
id
, int1
, int2
, (select count(*) from big_table_with_millions_of_rows 
    where id between t.int1 and t.int2)
from myTable t
where
....

この選択では、正確に 1 行が返されます。インライン選択で使用される ID は、インデックス付きの列 (主キー) です。andをこの 1 つの行から返された int1/int2 の値に置き換えるt.int1と、クエリはミリ秒で完了します。t.int2上記のクエリを実行すると、つまり int1/int2 への参照を使用すると、約 10 分かかります。プロファイラーを実行して実際に何が起こっているかを確認すると、99% の時間、エンジンがインライン クエリからデータを返すためにビジーであることがわかります。MySql が実際に実行されているように見えます。

select ... from big_table_with_millions_of_rows 

を適用する前に、インライン クエリのビットを 1 回

where id between t.int1 and t.int2

結果にビット。これは本当ですか?そうでない場合、何が起こっているのですか?SELECTinlineは、クエリの最後の要素として行ごとに実行されるため、潜在的に危険であると常に考えていましたが、このような状況では、イニシャルSELECTが非常に選択的であり、非常に効率的です。誰でもこれに光を当てることができますか?

編集:これまでのフィードバックに感謝します。私の懸念は、インラインクエリの行ごとの性質についてではなく、(同じ) ハードコーディングされた値ではなく、変数に直面したときに主キーインデックスを使用できないように見えるという事実です。私の推測では、ANALYZE が最近実行されていない場合、オプティマイザは、データ分散に関する知識がないため、テーブル スキャンを実行する必要があると想定します。しかし、範囲検索が主キーで行われるという事実は、それを補うものではないでしょうか?

4

3 に答える 3

1

可能であれば、JOINを使用して、相関するサブクエリを回避するようにしてください。

YouTubeでMySQLのパフォーマンスに関するこの素晴らしいビデオをご覧ください。31:00分に移動します。スピーカーのJayPipesが、相関するサブクエリの回避について話します。

于 2009-12-11T22:02:54.840 に答える
1

相関サブクエリが最適化されていない場合は、次のクエリを試してください。

select
  t.id
, t.int1
, t.int2
, count(*)
from myTable t
left outer join big_table_with_millions_of_rows b
  on (b.id between t.int1 and t.int2)
where
....
group by t.id

それははるかに最適化するはずです。


あなたの更新された質問について: そうです、最適化に関して、MySQL は市場で最も洗練された RDBMS ではありません。MySQL がこのようなコーナー ケースを最適化できない場合でも驚かないでください。

私は MySQL の使いやすさとオープン ソースなどの優れた機能のファンですが、実際のところ、競合他社はテクノロジーの点で MySQL よりもはるかに進んでいます。すべての RDBMS にはいくつかの「盲点」がありますが、MySQL のほうが大きいようです。

また、最新バージョンの MySQL を使用していることを確認してください。リリースごとにオプティマイザが改善されるため、新しいバージョンでより良い結果が得られる可能性があります。

于 2009-12-12T06:00:28.717 に答える
0

サブクエリがそれを含むクエリのフィールドを参照する場合、サブクエリは、参照されるフィールドが各行で異なる可能性があるため、含むクエリのすべての行ごとに再実行する必要があります。完全に自己完結型の場合は、外側のクエリが処理を開始する前に 1 回実行できます。

于 2009-12-11T20:19:29.373 に答える