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

这是对 3-5 百万记录表的繁重查询,即使我有活动索引:

item_index (item_id, lat, lng, created_at)

这不会在 EXPLAIN 中使用,它只是默认为“item_id”。我想我要问的是 - 需要添加哪些索引才能使此查询快速运行,或者我可以进行优化吗?

4

2 回答 2

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 回答
0

索引可用于where子句、on子句或两者。

where子句中,列 A、B 和 C(按此顺序)的索引可用于以下情况:

  • A 上的等式 eg ( A = a)
  • A 上的有序比较(例如A < aA > a
  • A 和 B 相等(例如A = a and B = b
  • A 上的相等,B 上的有序比较(例如A = a and B < b
  • A 和 B 和 C 上的平等
  • A 和 B 的相等性和 C 的有序比较

您的where子句具有相等性,然后是两个有序比较。我建议将a.lnga更改between为 anin并将索引更改为item_index (item_id, lng, lat, created_at).

您还应该删除索引,item_index(item_id)因为它不需要。这个新索引可以在任何地方使用。

由于order by rand(),此查询必须在返回任何行之前生成整个结果集。真正提高性能的唯一方法是希望where条件具有高度选择性,因此它们会减小生成集的大小。

activity如果您可以构造查询以从or中获取 5 行item然后执行连接,您可能会更好。

于 2013-02-07T01:08:35.890 回答