0

次のテーブルがあります。

items (item_id (PRIMARY), item_name)
activity (activity_id (PRIMARY), item_id (INT), user_id (INT), lat (FLOAT), lng (FLOAT), created_at)

次のクエリを実行したいと思います。

SELECT
  i.item_id,
  i.item_name,
  count(distint a.user_id) as total_count
FROM activity as a
  INNER JOIN item as i
    on a.item_id = i.item_id
WHERE (a.lat BETWEEN XXXXXXX
       and XXXXXXX
       and a.lng BETWEEN XXXXXXX
       and XXXXXXX)
    and created_at >= DATE_SUB(NOW(), INTERVAL 5 DAY)
GROUP by a.bid
ORDER BY RAND()
LIMIT 5

アクティビティに関するインデックスがあるにもかかわらず、これは 300 万から 500 万のレコード テーブルに対する負荷の高いクエリです。

item_index (item_id, lat, lng, created_at)

これは EXPLAIN では使用されず、デフォルトで「item_id」になります。私が求めているのは、このクエリを高速に実行するにはどのインデックスを追加する必要があるか、または最適化できるものがあるかということです。

4

2 に答える 2

0

where索引は、節、on節、またはその両方に使用できます。

句では、where列 A、B、および C (この順序で) のインデックスは、次の状況で使用できます。

  • A の等価性 例 ( A = a)
  • A の順序付き比較 (例:A < aまたはA > a)
  • A と B が等しい (例A = a and B = b)
  • A での等価性、B での順序付き比較 (例A = a and B < b)
  • A と B と C が等しい
  • A と B の等価性と C の順序付き比較

あなたのwhere句には等値があり、次に2つの順序付き比較があります。a.lngをabetweenから aninに変更し、インデックスを に変更することをお勧めしitem_index (item_id, lng, lat, created_at)ます。

インデックスもitem_index(item_id)不要なので削除する必要があります。この新しいインデックスは、どこでも使用できます。

のためorder by rand()、このクエリは行を返す前に結果セット全体を生成する必要があります。whereパフォーマンスを実際に改善する唯一の方法は、条件が非常に選択的であることを期待することです。これにより、生成されるセットのサイズが縮小されます。

activityまたはから5行を取得itemしてから結合を行うようにクエリを構成できる場合は、より良い結果が得られる可能性があります。

于 2013-02-07T01:08:35.890 に答える
0

このような派生サブクエリを試してください

SELECT
  i.item_id,
  i.item_name,
  count(distint a.user_id) as total_count
FROM activity as a
  INNER JOIN (select
        item_id,
        item_name
          from item
          where a.lat BETWEEN XXXXXXX
          and XXXXXXX
          and a.lng BETWEEN XXXXXXX
          and XXXXXXX) as i
    on a.item_id = i.item_id
WHERE created_at >= DATE_SUB(NOW(), INTERVAL 5 DAY)
GROUP by a.bid
ORDER BY RAND()
LIMIT 5
于 2013-02-06T20:09:02.673 に答える