2017-09-22 30 views
0

我目前正在優化我們的Web應用程序,我不確定如何從這裏開始:有一個大的SQL數據庫,其中包含一個包含數百萬個條目的大型歸檔表。這些行需要儘可能快地顯示在我們的可視化中(通過一個或兩個字段和一個時間戳過濾並通過Ajax傳遞到客戶機中的JS部分)。我在數據庫中創建了有用的索引,並且我也消除了通過我的歸檔實體中的導航屬性進行交叉引用的需要,這樣我就可以從一個表中只讀取數據,並在前端執行其他操作,從而大大提高了性能。我發現一個問題:我沒有要求所有的匹配前端數據(沒有人一次觀看10000行),而是使用skip()完成的分頁機制,並採取( )在服務器端。這也很好,很快,但爲了獲得匹配行的總量,我必須在某個地方進行計數。這個count()非常昂貴:從前端完整的請求週期和一些過濾器通常需要大約10到30毫秒,但是當我爲查詢添加一個計數時,這會增加到大約450 ms。加載分頁數據時行計數對性能有什麼影響?

現在我想知道如何繼續下去:我應該忽略這種延遲,只是和它一起生活嗎?或者是否有一種很好的方式來在不知道元素總數的情況下進行分頁?我的意思是,不知何故,前端需要知道行數,因爲它需要計算頁數並啓用/禁用「下一頁」按鈕等。

是否有解決此問題的好方法?

更新:這裏是我的代碼有一些意見:

var query = from x in db.ValueArchive select x; 

// Filter by DatapointIds, if there are any 
if (request.DatapointIds.Count>0) 
{ 
    query = query.Where(x => request.DatapointIds.Contains((int)x.DataPointId)); 
} 

// Filter by StationIds, if there are any 
if (request.StationIds.Count > 0) 
{ 
    query = query.Where(x => request.StationIds.Contains((int)x.StationId)); 
} 

// Get number of matching rows after filtering 
// This is the bottleneck! 
response.numFound = query.Count(); 

// Paging 
query = query.OrderBy(x => x.ID).Skip(request.Start == 0 ? 0 : request.Start-1).Take(request.Length); 

// Add paging info to response 
response.Start = request.Start; 
response.Length = request.Length; 

// Convert datetimes to ISO8601 
response.Rows = query.Select(x => new { d = x.DataPointId, s = x.StationId, t = x.DateValue.Value, v = x.Value }) 
    .ToList() 
    .Select(x => new { d = x.d, s = x.s, t = x.t.ToString("o"), v = x.v }).ToList<Object>(); 
+0

任何代碼可能? – SeM

+0

你可以嘗試分區。儘管沒有代碼,但我無法給你任何具體的想法。 – PacoDePaco

+1

另外,列存儲索引可以對聚合查詢的性能做出奇蹟 – PacoDePaco

回答

2

要執行SELECT COUNT(*),SQL Server將使用最窄非聚集索引計算所有行。所以,如果表沒有任何非聚集索引,它將不得不掃描整個表。 如果你有一個,那麼你可以使用這個(更多信息here):

SELECT OBJECT_NAME(s.id) [YourTable], s.rowcnt [Row_Count] 
FROM sys.sysindexes s WITH (NOLOCK) 
WHERE s.indid in (0,1) 
ORDER BY s.rowcnt desc 

作爲一種變通方法,您可以使用Microsoft用於快速顯示的行數的技術,當你右擊在桌子上,選擇屬性。

select sum (spart.rows) 
from sys.partitions spart 
where spart.object_id = object_id(’YourTable’) 
and spart.index_id < 2 

您可以使用ADO來執行這個(或使SQL函數)的代碼,讓你的結果(而不是運行在你的實體count()法)。

+0

謝謝,這是一個很好的技巧,我已經用它來獲得該表的* total *行數(它比count快50倍)。不幸的是,我不能用它來獲得過濾後的行數。 – Robert

+0

@Robert那麼如果你通過調用'query.ToString()'從你的'query'中創建SQL字符串,然後把它包裝到那個字符串並執行?如果可能,我還不太確定,但我會測試並通知您。 – SeM

+0

SeM,問題是我不需要整個表的行數,我需要爲我的查詢應用* where()*後得到的行數。不幸的是,上述技巧不允許。 – Robert

1

還是有沒有一種很好的方式來做分頁,而不知道總數 元素的數量?

是的,這是可能的 你不必調用count()來獲得總分頁數的項目。 項目COUNT不是強制性的。

在一個時間點,的PageIndex = N,如果返回的項目數< pageSize的==> n是最後一頁

  • 點擊返回==>獲得物品的PageIndex = N-1。
  • click next ==> get pageIndex = n + 1。

=>這樣,讓你不得不瀏覽的頁面一步一步(最流行的行爲,我認爲)

在這種情況下有一個人點擊最後=>只有在這種情況下,你必須得到項目數量。讓我們看看你如何谷歌搜索。你有沒有瀏覽過最後一頁?

+0

你說得對,從用戶的角度來看,這可能是最好的選擇。這就是最終的結果。 – Robert

相關問題