我有以下表格:
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”。我想我要问的是 - 需要添加哪些索引才能使这个查询快速运行,或者我可以进行优化?
答案 0 :(得分: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
答案 1 :(得分:0)
该索引可用于where
子句,on
子句或两者。
在where
子句中,A,B和C列的索引(按此顺序)可用于以下情况:
A = a
)A < a
或A > a
)A = a and B = b
)A = a and B < b
)您的where
子句具有相等性,然后是两次有序比较。我建议将a.lng
从between
更改为in
,并将索引更改为item_index (item_id, lng, lat, created_at)
。
您还应该删除item_index(item_id)
上的索引,因为它不需要。这个新索引可以在任何地方使用。
由于order by rand()
,此查询必须在返回任何行之前生成整个结果集。真正提高性能的唯一方法是希望where
条件具有高度选择性,因此它们会减小生成集的大小。
如果您可以构建查询以从activity
或item
获取5行然后执行连接,那么您可能会感觉更好。