[英]SQL Query results pagination with random Order by in SQL Server 2008
[英]Store results of SQL Server query for pagination
在我的數據庫中,我有一個包含相當大數據集的表,用戶可以在其上執行搜索。 因此,對於包含大約250,000條記錄的Person
表的以下表結構:
firstName|lastName|age
---------|--------|---
John | Doe |25
---------|--------|---
John | Sams |15
---------|--------|---
用戶將能夠執行可返回約500個左右結果的查詢。 我想做的是允許用戶使用分頁一次查看他的搜索結果50。 我已經找到了客戶端分頁的東西,但我需要在某處存儲查詢結果,以便分頁使用來自其唯一查詢的結果而不是SELECT *
語句。
誰能提供一些指導,以達到這個目標的最佳方法? 謝謝。
旁注:我一直在嘗試使用臨時表通過使用SELECT INTO
語句來執行此操作,但我認為這可能會導致一些問題,例如,用戶A執行搜索並且他的結果存儲在臨時表中然后用戶B不久后執行搜索,並覆蓋用戶A的搜索結果。
在SQL Server中, ROW_NUMBER()
函數非常適合分頁,並且可能會有所幫助,具體取決於搜索之間的參數變化,例如,如果搜索只是針對您可以使用的不同firstName值:
;WITH search AS (SELECT *,ROW_NUMBER() OVER (PARTITION BY firstName ORDER BY lastName) AS RN_firstName
FROM YourTable)
SELECT *
FROM search
WHERE RN BETWEEN 51 AND 100
AND firstName = 'John'
您可以添加其他ROW_NUMBER()
行,根據要搜索的字段更改PARTITION BY
子句。
首先,確保你真的需要這樣做。 你增加了很大的復雜性,所以去測量一下查詢和分頁是否真的很痛,或者你只是“覺得你應該”。 可以很容易地使用ROW_NUMBER()處理分頁。
假設你繼續,一旦你得到了你的查詢,顯然你需要建立一個緩存,所以首先你需要確定密鑰是什么。 它將是SQL語句或操作標識符(可能是存儲過程的名稱)和使用的標准。 如果您不想在用戶之間共享,那么也可以使用用戶名或某種會話ID。
現在,當您進行查詢時,首先要在此表中查找所有關鍵數據
a)無法找到它,因此您運行查詢並添加到緩存,存儲條件/鍵和數據的數據或PK,具體取決於您是想要快照還是實時。 請記住,“實時”並不是因為其他用戶可能正在更改您下面的數據。
b)找到它,因此刪除結果(或將PK加入基礎表)並返回結果。
當然,現在你需要一個后台進程來清理緩存,因為緩存太長時間了。
就像我說的那樣 - 你應該在開始之前確保你需要這樣做。 在你給出的例子中,我認為這不值得。
從歷史上看,對我們來說,管理它的最佳方法是創建一個具有唯一名稱的完整新表。 然后,當您完成后,您可以安排表刪除。
如果可行,該表只包含一個索引id(一個簡單的序列:1,2,3,4,5)和作為查詢一部分的表的主鍵。 不是整個結果集。
您的分頁邏輯會執行以下操作:
SELECT p.* FROM temp_1234 t, primary_table p
WHERE t.pkey = p.primary_key
AND t.serial_id between 51 and 100
序列號是您的分頁索引。
所以,你最終得到的東西(注意,我不是SQL Server的人,所以請原諒):
CREATE TABLE temp_1234 (
serial_id serial,
pkey number
);
INSERT INTO temp_1234
SELECT 0, primary_key FROM primary_table WHERE <criteria> ORDER BY <sort>;
CREATE INDEX i_temp_1234 ON temp_1234(serial_id); // I think sql already does this for you
如果你可以推遲索引,它比首先創建它更快,但它最有可能是一個微小的改進。
此外,創建一個跟蹤表,您可以在其中插入表名和日期。 你可以在晚些時候(深夜)使用收割機進程來DROP日期表(比那些X小時更多)。
全表操作比插入和刪除單個表中的行要便宜得多:
INSERT INTO page_table SELECT 'temp_1234', <sequence>, primary_key...
DELETE FROM page_table WHERE page_id = 'temp_1234';
那太糟糕了。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.