2013-02-06 145 views
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”。我想我要问的是 - 需要添加哪些索引才能使查询运行得更快,或者是否可以进行优化?

回答

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 
0

索引一个derieved子查询可以被用于任一where子句,on子句,或两者。

where子句,在列的索引A,B,和C(按该顺序),可以在下列情况下使用:

  • 公平对甲例如(A = a
  • 有序上A(例如A < aA > a
  • 平等于A和B(例如A = a and B = b
  • 平等于A,下令对乙比较(例如A = a and B < b
  • 比较
  • 公平对A和B和C
  • 公平对A和B,并下令基于C比较

where条款具有平等的,然后两个有序的比较。我建议将a.lngbetween更改为in,并将索引更改为item_index (item_id, lng, lat, created_at)

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

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

如果您可以构建查询以从activityitem获取5行,然后执行连接,则可能会更好。

+0

我不知道你可以改变BETWEEN到IN?另外你在哪里获得user_name? – gregavola

+0

'between'到'in'的变化只是一种猜测。 'a.lng'好像是“语言”,似乎是离散的,但可能是别的。 'user_name'是我的错。 。 。我误读了'item_name'。 –