2016-05-06 61 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