我应该为这个膨胀的查询添加哪些SQL索引?

时间:2011-09-30 09:49:24

标签: mysql sql indexing

我想知道索引是否会加快此查询速度。我上次检查时需要9秒。流量表有大约300k行,列表和用户5k行。如果这只是一个糟糕的查询,我也会受到嘲笑/羞辱。我很久以前写过它。

它应该获得具有最多页面浏览量(流量)的列表。如果缺乏解释,请告诉我。

SELECT traffic_listingid AS listing_id, 
       COUNT(traffic_listingid) AS genuine_hits, 
       COUNT(DISTINCT traffic_ipaddress) AS distinct_ips, 
       users.username, 
       listings.listing_address,
       listings.datetime_created,
       DATEDIFF(NOW(), listings.datetime_created) AS listing_age_days 
FROM traffic 
  LEFT JOIN listings 
    ON traffic.traffic_listingid = listings.listing_id 
  LEFT JOIN users 
    ON users.id = listings.seller_id 
WHERE traffic_genuine = 1 
  AND listing_id IS NOT NULL 
  AND username IS NOT NULL 
  AND DATEDIFF(NOW(), traffic_timestamp) < 24 
GROUP BY traffic_listingid 
ORDER BY distinct_ips DESC
LIMIT 10

P.S。

ENGINE=MyISAM /
MySQL Server 4.3

2 个答案:

答案 0 :(得分:3)

图片的标题说明:

1.你有

  LEFT JOIN listings 
    ON traffic.traffic_listingid = listings.listing_id 
  ...
WHERE ... 
  AND listing_id IS NOT NULL 

此条件取消LEFT JOIN。将您的查询更改为:

  INNER JOIN listings 
    ON traffic.traffic_listingid = listings.listing_id 

并从listing_id IS NOT NULL条件中移除WHERE

同样的事情也适用于LEFT JOIN userusername IS NOT NULL


2.检查traffic_timestamp

      DATEDIFF(NOW(), traffic_timestamp) < 24

使索引难以使用。将其更改为可以使用索引的类似内容 (并检查我的版本相同,我可能有错误):

      traffic_timestamp >= CURRENT_DATE() - INTERVAL 23 DAY

3. COUNT(non-nullable-column)相当于COUNT(*)。改变:

   COUNT(traffic_listingid) AS genuine_hits, 

为:

   COUNT(*) AS genuine_hits, 

因为它在MySQL中有点快(虽然我不确定版本4.3)


对于索引问题,您应该在每个用于加入的列上至少有一个索引。为traffic_timestamp添加一个也可能会有所帮助。

如果您告诉我们traffic_ipaddresstraffic_timestamp在哪些表格中,以及EXPLAIN EXTENDED显示的内容,可能会有更好的想法。

再次阅读查询,它似乎仅在表GROUP BY中为traffic,而其他2个表用于获取参考数据。因此,查询等同于(traffic group by)-join-listing-join-user。不确定这对你的MySQL旧版本是否有帮助,但如果一个查询在你的系统中运行得更快,那么拥有查询和测试的两个版本可能会很好。

答案 1 :(得分:0)

索引应始终放在您在where子句中使用的列上。

在这种情况下,listingid看起来是一个不错的选择,以及users.id,seller_id和traffic_timestamp。

在查询前使用EXPLAIN EXTENDED查看MySQL建议您使用的内容(显示触摸的行数以及使用的索引)