选择前100行后如何停止或限制选择?

时间:2013-12-05 08:53:39

标签: mysql performance optimization query-optimization limit

我有这样的查询 -

SELECT c.msisdn,SUM(c.dataVolumeDownLink+c.dataVolumeUpLink) AS datasum 
FROM cdr c 
WHERE c.eveDate>='2013-10-29'
GROUP BY c.msisdn 
ORDER BY datasum DESC;

这一节花了4分钟。我有一个关于evedate的索引。

CDR表包含从“2013-10-01”到“2013-10-30”每天的2400000条记录。但我想只选择前100条记录。我如何优化此查询。

我使用了限制条款,但它没有任何好处。

所以,请告诉我如何优化此查询。

谢谢。

4 个答案:

答案 0 :(得分:1)

你刚才提出

LIMIT 100

之后.... ORDER BY datasum DESC here ;

like .... ORDER BY datasum DESC LIMIT 100;

答案 1 :(得分:1)

如果记录均匀分布,一天将有80k行。超过80k的GROUP BY操作可能不需要4分钟(我猜)

我不确定你有以下索引:

INDEX(eveDate, msisdn)

使用上面的索引,记录按eveDate和msisdn排序,因此优化了GROUP BY操作。即,相同的msisdns位于同一块。我想以下查询比你的查询更快。

<强> Q1

SELECT x.msisdn, SUM(datasum)
FROM
(
    SELECT c.msisdn AS msisdn,
        SUM(c.dataVolumeDownLink+c.dataVolumeUpLink) AS datasum 
    FROM cdr c 
    WHERE c.eveDate>='2013-10-29'
    GROUP BY eveDate, c.msisdn 
) x
GROUP BY x.msisdn
ORDER BY SUM(datasum)
LIMIT 100;

或类似的东西。

<强> Q2

SELECT c.msisdn SUM(c.dataVolumeDownLink+c.dataVolumeUpLink) AS datasum 
FROM cdr c 
WHERE c.eveDate>='2013-10-29'
GROUP BY c.msisdn 
ORDER BY 100;

上面的查询更简单,但同样的msisdn可以位于另一个eveDate中。所以INDEX(eveDate, msisdn)的好处有点儿。如果磁盘具有较大的可用空间,则在INDEX之后仅执行INDEX扫描。不需要数据。所有要求都在INDEX

INDEX(eveDate, msisdn, dataVolumeDownLink, dataVolumeUpLink)

已更新

嗯,如果仅附加数据,则永远不会更改附加数据。我想知道是否每天都做汇总表。

CREATE TABLE summary(eveDate, msisdn, datasum, INDEX(eveDate, msisdn);

每晚通过cronjob运行以下查询

INSERT INTO summary
SELECT NOW() c.msisdn,SUM(c.dataVolumeDownLink+c.dataVolumeUpLink) AS datasum 
FROM cdr c 
WHERE c.eveDate = NOW()
GROUP BY c.msisdn 

然后你的查询会非常简单。

SELECT msisdn, SUM(datasum) as datasum
FROM summary
WHERE eveDate BETWEEN ? AND ?

答案 2 :(得分:0)

SELECT c.msisdn,SUM(c.dataVolumeDownLink+c.dataVolumeUpLink) AS datasum 
FROM cdr c 
WHERE c.eveDate>='2013-10-29'
GROUP BY c.msisdn 
ORDER BY datasum DESC
LIMIT 0, 100;

答案 3 :(得分:0)

SELECT c.msisdn,SUM(c.dataVolumeDownLink+c.dataVolumeUpLink) AS datasum 
FROM 
(select * from cdr where eveDate>='2013-10-29' limit 100) as c 

GROUP BY c.msisdn 
ORDER BY datasum DESC;

拉里回答的微小变化
不完全确定我是否正确理解了这个问题
这将首先获取前100条记录并对其进行计算。 因此,最终结果可能少于100行,基于group by子句

编辑:
根据您的说明,您需要在c.msisdn上添加一个索引并在末尾添加一个限制子句
删除order by子句并放置一个外部查询,以便按< / p>

SELECT a.* FROM (
SELECT c.msisdn,SUM(c.dataVolumeDownLink+c.dataVolumeUpLink) AS datasum 
FROM cdr c 
WHERE c.eveDate>='2013-10-29'
GROUP BY c.msisdn limit 100) a 
ORDER BY a.datasum DESC;

在c.msisdn

上添加索引