1

テーブルには 2mのordersレコードがあります。~900Kship-to-idのユニークな があります。

ship_to_id( フィールドは)にインデックスがありますint(8)

以下のクエリは、完了するまでに約 10 分かかります。=と=PROCESSLISTを持っているものを実行しました。CommandQueryStateSending Data

を実行するexplainと、既存のインデックスが使用されpossible_keysNULL.

このクエリを高速化するためにすべきことはありますか? ありがとう。

SELECT 
  ship_to_id as customer_id 
FROM orders 
GROUP BY ship_to_id 
HAVING SUM( price_after_discount ) > 0
4

3 に答える 3

4

便利なインデックスがあるようには見えません。price_after_discount にインデックスを追加して、次のように where 条件を追加してみてください。

WHERE price_after_discount > 0

明らかに0の行を破棄できるため、合計する必要がある行の数を最小限に抑えることができます。

また、「top」コマンドを実行してみて、クエリの実行中に io の「wait」列を確認してください。値が高い場合は、クエリが大量のディスク I/O を引き起こしていることを意味します。これを高速化するための RAM がある場合 (innodb を使用している場合)、または myisam がファイルシステムのキャッシュを通じて行われる場合は、さまざまなメモリ バッファーを増やすことができます。サーバーを再起動すると、これらのキャッシュがフラッシュされます。

十分な RAM がない場合 (2M レコードにはあまり必要ないはずです)、おそらく ship-to-ids 列に対するパーティション分割スキームを検討してください (mysql のバージョンがサポートしている場合)。

于 2013-05-08T19:27:07.240 に答える
2

そのテーブルのすべての注文が最新ではない (つまり、再び変更される予定がない) 場合は、それらを別のテーブルにアーカイブして、スキャンする必要があるデータの量を減らすことができます。

別のオプションはlast_modified、インデックスを使用してテーブルにタイムスタンプをスローすることです。その後、クエリがいつ実行されたかを追跡し、結果を別のテーブルに保存できます ( query_results)。クエリを再度実行するときは、前回のクエリ実行以降に変更された注文を選択するだけで済み、それを使用してquery_results. ロジックはもう少し複雑ですが、クエリ実行間で更新される注文の割合が低いと仮定すると、はるかに高速になるはずです。

于 2013-05-08T19:47:40.410 に答える
2

ここで説明されているように、少なくともドキュメントによると、MySQLa のインデックスを使用します。group by

最も有用であるためには、クエリで使用されるすべての列がインデックスに含まれている必要があります。これにより、エンジンが元のデータとインデックスを参照する必要がなくなります。でインデックスを試してみてくださいorders(ship_to_id, price_after_discount)

于 2013-05-08T19:47:44.953 に答える