1
SELECT COUNT(*) AS count_all, products.id AS products_id 
FROM `products` 
INNER JOIN `product_device_facilities` 
  ON `product_device_facilities`.`product_id` = `products`.`id` 
INNER JOIN `product_vendors` 
  ON `product_vendors`.`ProductId` = `products`.`id` 
INNER JOIN `screen_shots` 
  ON `screen_shots`.`ProductVendorId` = `product_vendors`.`id` 
WHERE ( (DownloadCount >= 10 or DownloadCount is NULL) 
  and (Minsdk <= 10 or Minsdk is null)) 
GROUP BY products.id 
HAVING GROUP_CONCAT(device_facility_id ORDER BY device_facility_id ASC ) IN (0)

これは、100kレコードの場合に10秒かかります。

パフォーマンスを向上させる方法は?

4

3 に答える 3

4

試すことができることがいくつかあります。

  1. データベースへの永続的な接続を使用して、接続のオーバーヘッドを回避します
  2. すべてのテーブルのキーテーブルに主キーがあることを確認します(例:(product_id))
  3. 格納されている値を保持するために必要な大きさの列のみを宣言することにより、行あたりのRAMの使用量を減らします。つまり、@ manurajhadaが言ったように、count(*)は使用しないでくださいcount(主キー)を使用してください
  4. GRANTステートメントを発行するときに単純なパーミッションを使用すると、MySQLでパーミッションチェックのオーバーヘッドを減らすことができます。
  5. 異なるテーブル間の参照にインデックスを使用します。あまりにも多くの列にインデックスを付けないように注意してください。簡単な経験則です。比較で列を参照しない場合は、インデックスを付ける必要はありません。
  6. ANALYZE TABLEを使用して、mysqlがクエリをより適切に最適化できるようにしてください。
  7. nullではないすべての列がNOTNULLとして宣言されていることを確認することで、クエリを少し高速化できます。したがって、テーブルのトラバースを少し高速化できます。
  8. MySQLキャッシングを調整します。バッファに十分なメモリを割り当て(たとえば、SET GLOBAL query_cache_size = 1000000)、平均クエリ結果セットサイズに応じてquery_cache_min_res_unitを定義します。
  9. 直感に反しているように聞こえますが、テーブルを非正規化する価値がある場合があります。つまり、高価なJOINを回避するために、いくつかのデータを複数のテーブルに複製します。外部キーまたはトリガーを使用してデータの整合性をサポートできます。

そして他のすべてが失敗した場合

  1. 可能であればハードウェアをアップグレードし、RAMを増やし、HDDを高速化すると、データベースの速度に大きな違いが生じる可能性があります。アップグレードが完了すると、mysqlにより多くのメモリが割り当てられます。

編集

  • @ ask-bjorn-hansenが提案したように、結果をライブで必要としない場合の別のオプションは、バックグラウンドタスク(cronジョブ)を1日1回使用し、クエリの結果を別のテーブルに保存してから、アプリケーションにすべてを保存することです。そのテーブルで返された結果を確認する必要があります。そうすれば、10万件の結果をクエリする必要がなくなり、ユーザーに過度の影響を与えずに数時間かかるクエリを実行できるようになります。
于 2012-05-31T10:13:03.153 に答える
1

テーブルの結合列でインデックスを作成し、count(*)の代わりにcount(インデックス付きの主キー列)を使用します。

于 2012-05-31T09:44:16.250 に答える
1

minsdkとダウンロード数は同じテーブルにありますか?その場合、これら2つにインデックスを追加すると役立つ場合があります。

すばやく実行するのは難しい/不可能なクエリである可能性があります。完全なスキーマとデータを確認しないと、特定するのは困難ですが、実行しやすいクエリに分割する方が速い可能性があります。または、Amadeusが提案したように、データを少し非正規化する可能性があります。

もう1つのバリエーションは、10秒かかるだけですが、ユーザーが待機している間は絶対にバックグラウンドで(cronなどを使用して)定期的に実行するようにしてください。次に、数秒ではなく数分かかる場合や、ユーザーエクスペリエンスやサーバーに許容できない負担がかかる場合は、時間をかけて修正してください。

于 2012-05-31T10:20:05.610 に答える