如何使用其中的一些子查询来优化此查询

时间:2013-03-18 10:05:46

标签: mysql query-optimization subquery

我的查询是这样的:

SELECT date_format( created_at, '%Y-%m-%d' ) AS the_date, 
COUNT(s.id) AS total, 
(SELECT COUNT(ks.id) FROM kc_shares ks WHERE site = 'facebook' AND date_format( created_at, '%Y-%m-%d' ) = the_date ) AS total_facebook, 
(SELECT COUNT(ks.id) FROM kc_shares ks WHERE site = 'twitter' AND date_format( created_at, '%Y-%m-%d' ) = the_date ) AS total_twitter 
FROM `kc_shares` s
GROUP BY `the_date`

我想得到的是每日股票的数量,包括总数,Facebook总份额(因此site ='facebook')和twitter的总股数。这就是我需要GROUP BY

的原因

当它有几千行时,没有问题。但该表目前有近20万行,查询速度很慢,大约需要20-30秒,我想更多。

我尝试在site和created_at字段中添加索引,但无济于事。

由于

3 个答案:

答案 0 :(得分:1)

移动子选择,以便您加入它们,而不是为每个返回的行执行子选择。

像这样(未经测试): -

SELECT date_format( created_at, '%Y-%m-%d' ) AS the_date, 
COUNT(s.id) AS total, 
Sub1.total_facebook, Sub2.total_twitter
FROM `kc_shares` s
LEFT OUTER JOIN (SELECT date_format( created_at, '%Y-%m-%d' ) AS sub_date, COUNT(ks.id) AS total_facebook FROM kc_shares ks WHERE site = 'facebook' GROUP BY sub_date ) Sub1 ON date_format( created_at, '%Y-%m-%d' ) = Sub1.sub_date
LEFT OUTER JOIN (SELECT date_format( created_at, '%Y-%m-%d' ) AS sub_date, COUNT(ks.id) AS total_twitter  FROM kc_shares ks WHERE site = 'twitter' GROUP BY sub_date ) Sub2 ON date_format( created_at, '%Y-%m-%d' ) = Sub2.sub_date
GROUP BY `the_date`

虽然找到一种在非派生列上进行连接的方法(即日期/时间的日期部分)也会有所帮助。这可能是一个很好的例子,用于一点或非规范化,只为日期和时间添加一个字段添加到当前存储的日期/时间。

答案 1 :(得分:1)

我认为子查询正在消耗性能。所以也许你可以这样做:

SELECT 
    date_format( created_at, '%Y-%m-%d' ) AS the_date, 
    COUNT(s.id) AS total, 
    SUM(CASE WHEN s.site='facebook' THEN 1 ELSE 0 END) AS total_facebook, 
    SUM(CASE WHEN s.site='twitter' THEN 1 ELSE 0 END) AS total_twitter
FROM 
    `kc_shares` s
GROUP BY 
    `the_date

`

答案 2 :(得分:0)

另一种方法是更改​​查询的工作方式。以下内容将为每天/站点提供行,而不是将两个站点放在同一行上。

SELECT 
   date_format( created_at, '%Y-%m-%d' ) AS the_date,site, 
   count(id) 
FROM 
   kc_shares s 
where 
   (site="facebook" or site="twitter") ) 
group by  
   created_at, site

我假设created_at是一个日期字段。

这应该提供相同的数据(我想,我还没有尝试过),但是格式不同。

在(created_at,site)上尝试索引。