2016-05-06 60 views
0

我得到了基本上相同的代码的2个版本。 (见下文)版本1运行时间为2秒,版本2运行时间为.5 - .6秒。目前我从中选择1000万行,但这个数字上升得相当快。如果可能,我想尽可能降低。问题是我使用版本2,我需要调用30次(不同的状态,不同的用户名等),最终的数字对我所需要的来说仍然太大。是否有我可以使用的第三个版本?或者还有什么其他的方式可以让这个更快?或者我唯一能做的就是玩索引。计数性能优化

基本上所有这些计数都会显示在Web应用程序中访问量最大的屏幕上,而当1000个用户在同一时间使用该系统时,30 * .5秒听起来有点太多。

版本1个

declare @a1 datetime; set @a1 = GETDATE() 

declare @int1 INT,@int2 INT,@int3 INT,@int4 INT,@int5 INT,@int6 INT,@int7 INT,@int8 INT 

select @int1 = COUNT(Id) from ToDos where StatusId = 1 and stringUserId = 'a' 
select @int2 = COUNT(Id) from ToDos where StatusId = 1 and stringUserId = 'b' 
select @int3 = COUNT(Id) from ToDos where StatusId = 1 and stringUserId = 'c' 
select @int4 = COUNT(Id) from ToDos where StatusId = 1 and stringUserId = 'd' 
select @int5 = COUNT(Id) from ToDos where StatusId = 1 and stringUserId = 'e' 
select @int6 = COUNT(Id) from ToDos where StatusId = 1 and stringUserId = 'f' 
select @int7 = COUNT(Id) from ToDos where StatusId = 1 and stringUserId = 'g' 
select @int8 = COUNT(Id) from ToDos where StatusId = 1 and stringUserId = 'h' 

select @int1, @int2, @int3, @int4, @int5, @int6, @int7, @int8 

SELECT DATEDIFF(MILLISECOND, @a1, GETDATE()) 

2版

declare @a1 datetime; set @a1 = GETDATE() 

select stringUserId, count(stringUserId) 
from ToDos 
where StatusId = 1 and stringUserId in ('a','b','c','d','e','f','g','h') 
group by stringUserId 
order by COUNT(stringUserId) desc 

SELECT DATEDIFF(MILLISECOND, @a1, GETDATE()) 
+0

为什么您需要拨打第二个版本30次? Afaik你只需要一个查询来选择所有必要的信息。你只需要删除'StatusId'过滤器。将它添加到“Group By”。然后结果包含所有状态的计数,这似乎是你需要的。 –

+0

性能问题应该包括'EXPLAIN ANALYZE'和一些关于表格大小,索引,当前时间表现,期望时间等的信息。'Slow'是一个相对术语,我们需要一个实际值来比较。 [** MySQL **](http://dba.stackexchange.com/questions/15371/how-do-i-get-the-execution-plan-for-a-view) 使用[查询分析器](https://technet.microsoft.com/en-us/library/aa216945(v=sql.80).aspx) –

+0

@JuanCarlosOropeza:这是sql-server不是mysql。但无论如何你是对的 –

回答

1

尝试有条件计数。

select 
    @int1 = COUNT(CASE WHEN stringUserId = 'a' THEN 1 END), 
    @int2 = COUNT(CASE WHEN stringUserId = 'b' THEN 1 END), 
    @int3 = COUNT(CASE WHEN stringUserId = 'c' THEN 1 END), 
    @int4 = COUNT(CASE WHEN stringUserId = 'd' THEN 1 END), 
    @int5 = COUNT(CASE WHEN stringUserId = 'e' THEN 1 END), 
    @int6 = COUNT(CASE WHEN stringUserId = 'f' THEN 1 END), 
    @int7 = COUNT(CASE WHEN stringUserId = 'g' THEN 1 END), 
    @int8 = COUNT(CASE WHEN stringUserId = 'h' THEN 1 END) 
from ToDos 
where StatusId = 1 

FYI:我没有包括ELSE一部分CASE因为默认情况下将返回NULLCOUNT犯规数零点

+0

这个问题的任何更新?你能检查查询计划吗? –

0

你可以尝试:

select a.* from (select stringUserId, count(stringUserId) as IDCount 
from ToDos 
where StatusId = 1 and stringUserId in ('a','b','c','d','e','f','g','h') 
group by stringUserId) a 
order by a.IDCount desc 

从消除计数功能订购

+0

你确定这有所作为吗?因为'order by'已经在'group by'之后 –

+0

订单也必须计算计数。所以计数发生两次。我发现这种技术在过去对某些东西进行了改进,但没有访问OP的数据,我不知道它在这种情况下是否会有所帮助。写入查询中的顺序与数据库引擎可能决定执行操作的顺序没有任何关系。 – HLGEM