2013-03-18 72 views
0

我的查询是这样的:如何在其优化这个查询一些子查询

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(因此网站='脸谱')和总分享到微博。这就是为什么我需要GROUP BY

当它有几千行时,没有问题。但是这张表目前有近20万行,查询速度非常慢,大约需要20-30秒,我猜更多。

我已经尝试添加索引到网站和created_at字段,但无济于事。

太感谢你加入反对他们,而这样做子查询为每个返回的行

回答

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 

`

+0

这个工程!谢谢! – Henson 2013-03-18 12:24:58

+0

没问题。乐意效劳! – Arion 2013-03-18 13:11:23

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` 

虽然找到一种方法,做一个非派生列联接(即日期/时间的日期部分)也会有所帮助。可能是一个很好的例子,在这里稍微或反规范化,为当前存储的日期/时间增加一个仅用于日期的字段。

+0

我试着将它移动到连接,它好多了,查询现在需要6-8秒,但@Arion给了完美的解决方案。虽然谢谢! – Henson 2013-03-18 12:26:11

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是一个日期字段。

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

尝试索引on(created_at,site)。

+0

我在子查询中使用它的原因是因为select中会有另一个聚合。所以它就像count(id)作为总数,count(something_id)作为total_something等等。因此,结果将被很好地格式化,这样我就可以循环每一天来获取共享的共享计数,无论他们是对Facebook还是twitter等加上其他汇总值。 – Henson 2013-03-18 12:21:04