sql大數據分頁
A. sql語句分頁查詢,一頁面多少數據合適
2萬條。
在SQLServer中通過SQL語句實現分頁查詢,在SQLServer中通過SQL語句實現分頁後插入數據2萬條,用更多的數據測試會明顯一些。微軟的SQLSERVER提供了兩種索引:聚集索引,也稱聚類索引、簇集索引和非聚集索引,也稱非聚類索引、非簇集索引。
建立一個web應用,分頁瀏覽功能必不可少。這個問題是資料庫處理中十分常見的問題。經典的數據分頁方法是:ADO紀錄集分頁法,也就是利用ADO自帶的分頁功能(利用游標)來實現分頁。但這種分頁方法僅適用於較小數據量的情形,因為游標本身有缺點:游標是存放在內存中,很費內存。游標一建立,就將相關的記錄鎖住,直到取消游標。游標提供了對特定集合中逐行掃描的手段,一般使用游標來逐行遍歷數據,根據取出數據條件的不同進行不同的操作。而對於多表和大表中定義的游標(大的數據集合)循環很容易使程序進入一個漫長的等待甚至死機。更重要的是,對於非常大的數據模型而言,分頁檢索時,如果按照傳統的每次都載入整個數據源的方法是非常浪費資源的。現在流行的分頁方法一般是檢索頁面大小的塊區的數據,而非檢索所有的數據,然後單步執行當前行。最早較好地實現這種根據頁面大小和頁碼來提取數據的方法大概就是「俄羅斯存儲過程」。這個存儲過程用了游標,由於游標的局限性,所以這個方法並沒有得到大家的普遍認可,後來,網上有人改造了此存儲過程,實現了分頁儲存。
B. sql2000最有效率的分頁sql 語句(解決大數據量)
/*
Function:
SuperPaging
*
Description:
*
超強通用分頁存儲過程
*
Example:
*
SuperPaging
@TableName='表名',@Orderfld='排序列名'
*/
CREATE
PROCEDURE
SupesoftPage
(
@TableName
nvarchar(50),
--
表名
@ReturnFields
nvarchar(2000)
=
'*',
--
需要返回的列
@PageSize
int
=
10,
--
每頁記錄數
@PageIndex
int
=
1,
--
當前頁碼
@Where
nvarchar(2000)
=
'',
--
查詢條件
@Orderfld
nvarchar(2000),
--
排序欄位名
最好為唯一主鍵
@OrderType
int
=
1
--
排序類型
1:降序
其它為升序
)
AS
DECLARE
@TotalRecord
int
DECLARE
@TotalPage
int
DECLARE
@CurrentPageSize
int
DECLARE
@TotalRecordForPageIndex
int
DECLARE
@OrderBy
nvarchar(255)
DECLARE
@CutOrderBy
nvarchar(255)
if
@OrderType
=
1
BEGIN
set
@OrderBy
=
'
Order
by
'
+
REPLACE(@Orderfld,',','
desc,')
+
'
desc
'
set
@CutOrderBy
=
'
Order
by
'+
REPLACE(@Orderfld,',','
asc,')
+
'
asc
'
END
else
BEGIN
set
@OrderBy
=
'
Order
by
'
+
REPLACE(@Orderfld,',','
asc,')
+
'
asc
'
set
@CutOrderBy
=
'
Order
by
'+
REPLACE(@Orderfld,',','
desc,')
+
'
desc
'
END
--
記錄總數
declare
@countSql
nvarchar(4000)
set
@countSql='SELECT
@TotalRecord=Count(*)
From
'+@TableName+'
'+@Where
execute
sp_executesql
@countSql,N'@TotalRecord
int
out',@TotalRecord
out
SET
@TotalPage=(@TotalRecord-1)/@PageSize+1
SET
@CurrentPageSize=@PageSize
IF(@TotalPage=@PageIndex)
BEGIN
SET
@CurrentPageSize=@TotalRecord%@PageSize
IF(@CurrentPageSize=0)
SET
@CurrentPageSize=@PageSize
END
--
返回記錄
set
@TotalRecordForPageIndex=@PageIndex*@PageSize
exec('SELECT
*
FROM
(SELECT
TOP
'+@CurrentPageSize+'
*
FROM
(SELECT
TOP
'+@TotalRecordForPageIndex+'
'+@ReturnFields+'
FROM
'+@TableName+'
'+@Where+'
'+@OrderBy+')
TB2
'+@CutOrderBy+')
TB3
'+@OrderBy)
--
返回總頁數和總記錄數
SELECT
@TotalPage
as
PageCount,@TotalRecord
as
RecordCount
GO
C. sql資料庫分頁
樓主,剛剛有個問友和你問的差不多,我剛回答了他的。就直接把剛回答的復制給你看看啦。希望對你有幫助、。
要想分頁,首先得做好准備工作。你要先聲明每頁顯示多少條數據,還得獲取當前選擇的是多少頁的頁碼。有了這兩個分頁就好辦了。
sql如下:select top 10 from tableName
where (id not in(select top 20 from tableName order by Id desc)) order by Id desc
分頁需要使用到的一些動態數據如下:
每頁顯示的數量:自己定義。
總頁數:數據總條數/每頁顯示的條數
當前頁碼的計算方法:(頁碼-1)*每頁顯示的數量。比如我要瀏覽第3頁的數據,3從客戶端傳送過來後,在後台對頁碼進行處理:(3-1)*每頁顯示的數量(假如是10).算出來後的結果就是20.你在把20以參數注入的方式動態添加到上面那個20那裡就ok了。
sql中的10表示你每頁顯示的數據,這里跟10,就代表每頁顯示10條。(你可以定義一個常量作為每頁顯示的條數)
where中的20表示不包括前面的20條數據,也就是查詢出從第21條到30之間的數據。
不知道我這樣說你是否理解,其實只要理解了sql語句,分頁就很好做了。
D. sql多表關聯,數據量比較大的分頁查詢,怎麼做,有沒有較好的方法,
可以做一個存儲過程,傳入參數的方式,參數可以有顯示第幾頁,分頁大小,可以返回總行數和查詢結果
E. (問題解決再追加100分)sql server存儲過程實現查詢數據條數過大,分頁查詢怎麼實現
按說5-8w這樣數量級的數據沒有問題,寫入Excel是布比較耗性能,主要還是要通過優化寫入Excel的代碼效率上去考慮。你可以考慮利用分批查詢寫入的方式來避免一次寫太多的數據到Excel:將你的查詢結果分段,比方你的語句中能不能用時間來認為分段,每次返回部分結果。
回到你的問題,對大數據量查詢的解決方案有以下兩種:
(1)、將全部數據先查詢到內存中,然後在內存中進行分頁,這種方式對內存佔用較大,必須限制一次查詢的數據量。
(2)、採用存儲過程在資料庫中進行分頁,這種方式對資料庫的依賴較大,不同的資料庫實現機制不通,並且查詢效率不夠理想。以上兩種方式對用戶來說都不夠友好。
2.解決思路
通過在待查詢的資料庫表上增加一個用於查詢的自增長欄位,然後採用該欄位進行分頁查詢,可以很好地解決這個問題。下面舉例說明這種分頁查詢方案。
(1)、在待查詢的表格上增加一個long型的自增長列,取名為「queryId」,mssql、sybase直接支持自增長欄位,oracle可以用sequence和trigger來實現。然後在該列上加上一個索引。
添加queryId列的語句如下:
Mssql: [QUERYID] [bigint] IDENTITY (1, 1)
Sybase: QUERYID numeric(19) identity
Oracle:
CREATE SEQUENCE queryId_S
INCREMENT BY 1
START WITH 1
MAXVALUE 999999999999999 MINVALUE 1
CYCLE
CACHE 20
ORDER;
CREATE OR REPLACE TRIGGER queryId_T BEFORE INSERT
ON "test_table"
FOR EACH ROW
BEGIN
select queryId_S.nextval into :new.queryId from al;
END;
(2)、在查詢第一頁時,先按照大小順序的倒序查出所有的queryId,
語句如下:select queryId from test_table where + 查詢條件 +order by queryId desc 。
因為只是查詢queryId欄位,即使表格中的數據量很大,該查詢也會很快得到結果。然後將得到的queryId保存在應用伺服器的一個數組中。
(3)、用戶在客戶端進行翻頁操作時,客戶端將待查詢的頁號作為參數傳遞給應用伺服器,伺服器通過頁號和queyId數組算出待查詢的queyId最大和最小值,然後進行查詢。
算出queyId最大和最小值的演算法如下,其中page為待查詢的頁號,pageSize為每頁的大小,queryIds為第二步生成的queryId數組:
int startRow = (page - 1) * pageSize
int endRow = page * pageSize - 1;
if (endRow >=queryIds.length)
{
endRow = this.queryIds.length - 1;
}
long startId =queryIds[startRow];
long endId =queryIds[endRow];
查詢語句如下:
String sql = "select * from test_table" + 查詢條件 + "(queryId <= " + startId + " and queryId >= " + endId + ")";
3.效果評價
該分頁查詢方法對所有資料庫都適用,對應用伺服器、資料庫伺服器、查詢客戶端的cpu和內存佔用都較低,查詢速度較快,是一個較為理想的分頁查詢實現方案。經過測試,查詢4百萬條數據,可以在3分鍾內顯示出首頁數據,以後每一次翻頁操作基本在2秒以內。內存和cpu佔用無明顯增長。
以上也僅僅是分頁查詢結果查看的問題,你需要寫入到Excel的話還需要考慮Excel寫入代碼的執行效率,這部分是很值得研究的。
F. sqlserver2000 如何提高分頁查詢大數據量的效率
sqlserver2005及以上的版本有row_number()函數可以高效分頁,sqlserver2000的話只能看演算法了
G. 對於多表關聯的,大數據分頁,怎麼整sql
SELECT*
FROM(SELECT查詢欄位,
ROW_NUMBER()OVER(ORDERBY排序欄位)ASNum
FROM表1a
INNERJOIN表2bONa.關聯欄位=b.關聯欄位
)t
WHEREt.NumBETWEEN10AND20
H. 大數據量實時統計排序分頁查詢(並發數較小時)的幾點建議
大數據量實時統計排序分頁查詢的瓶頸不是函數(count,sum等)執行,
不是having, 也不是order by,甚至不是表join, 導致慢的原因就在於「數據量太大本身」
就是將表劃分為M份相互獨立的部分,可以是分表,也可以是不分表但冗餘一個取模結果欄位
實際結果是不分表比分表更加靈活,只需稍加配置,就可以動態切分大表,隨意更改M的大小。
將1條慢sql(大於30秒)拆分成為N條查詢速度巨快的sql(單條sql執行時間控制在20毫秒以內)
然後再web應用中以適當的線程數去並發查詢這些執行時間快的N條小sql再匯總結果
第一步查詢中去並發執行這N條小sql, 只取排序欄位和標識欄位,其他欄位一律丟棄
匯總結果後定位出當前頁面要顯示的pageNum條數據,再進行第二步查詢,取出頁面上需要展示的所有欄位
PS:這一點是至關重要的,其他幾點都可以不看,這點是最關鍵的。慢慢解釋一下:
有三種方式統計所有的記錄,
a) 第一種方式是把資料庫中所有記錄(只取排序欄位和標識欄位並且不做任何sum,count having order by等操作)
全部拉到web應用中,在web應用中完成所有的計算
b) 第二種方式是把資料庫中所有記錄做sum count having等操作之後的所有行數拉到web應用中,在web應用中完成剩餘計算
c) 第三種方式是把資料庫中所有記錄做sum count having order by等操作之後把limit後的數據拉到web應用中,
在web應用中對limit後的數據再計算
顯然,第一種方式 資料庫什麼活都不做只取數據 是不可行的。以lg_order_count_seller為例,1500萬行,
如果只算id, seller_id和order_count 這三個bigint類型,至少需要拉8*3*1500 0000 = 360000000=340M,
拉到內存中之後存儲需要8*4*15000000= 460M,這還不算List是的2的n次方這個特點和計算排序等的內存開銷,
不僅資料庫與web應用機器IO扛不住,就是應用自身恐怕也要OOM了。
第二種方式,所有記錄做sum count having等操作之後,由於是group by seller_id的,總得數據量變為100萬(就是賣家總數),
這樣子一來,共需要拉8*3*100 0000 = 23M,拉到內存之後,需要8*4*100 0000 = 30M, 再算上List是的2的n次方這個特點和
計算排序等的內存開銷也不會超過100M, IO的時間和內存開銷勉強可以考慮接受。
第三種方式,所有記錄做sum count having order by等操作之後把limit後的數據拉到web應用中,因為做了limit,所以,
數據量很小了,無論是IO還是內存開銷都已經很小了。可以忽略。
綜合以上三種,第三種方式適用於頁面的前n頁和後n頁,因為這個limit的數據量隨著頁數的增大而增大,
當大到每個切分後的小表的數據量時就轉為第二種方式了。
第二種方式適用於頁面的第[n+1, totaoPageNum-n]頁。
① 問題描述:
優化之前,還是是一條大慢sql查詢時,由於資料庫排序是穩定排序,
所以當兩條記錄排序欄位值相同時他們在頁面上的頁碼位置是固定的。
優化之後,當並行執行這N條小sql時,由於無法控制這些小sql的先後執行順序,
導致在web應用中當兩條記錄的排序欄位值相同時在頁面上的頁碼位置是隨機的。
② 解決辦法:
除了拉標識欄位(seller_id)和排序欄位(order_count_sum)之外,再取一個unique(id)的欄位,當兩條記錄的排序欄位值相同時,
再用這個unique的欄位(在賣家監控中這個欄位是id)進行第二次排序.這樣就解決了排序不穩定的問題。
③ 也許,看到這里會有疑問,為什麼不用seller_id?seller_id也是唯一, 這樣子不是少取id這個欄位,減少IO了?
seller_id雖然也是唯一,可以輔助排序,但是不要忘記資料庫的排序規則是:
如果兩列的值相等,那麼序號在前的排在前面,這里的序號就是主鍵(自動生成,autoincrement),
如果用seller_id的話還是不能保證排序的穩定性,只能用主鍵id.
把資料庫的連接,掃表,計算等資源優先讓給用戶關注的主要元素,次要元素可等主要元素載入完成之後再載入。
反應在賣家監控頁面中,查數據和查頁頁碼的sql語句基本相同,是在競爭同一資源,
所以,需要做一個策略,優先把資源讓給查數,數據查完之後再去查頁碼。
由於多線程取數據並沒有從本質上提高資料庫性能,所以必須針對大數據量實時統計排序分頁查詢做限流
我這里打個比方:食堂有6個窗口,物流團隊吃飯要買6個菜,平均每買1個菜需要1分鍾的時間,
如果派我一個人去一個窗口買的話需要6分鍾的時間
假如派6個人分別去6個窗口買這6個菜,只需要1分鍾的時間
但是,如果除了物流團隊,再來其他5個團隊呢,也就是說6個團隊每個團隊買6個菜共買36個菜,
這樣子有的團隊先買完,有的團隊後買完,但平均時間還是6分鍾。本質上沒有變化。
所以,對於特定的查詢條件,必須進行限流。讓每分鍾至多有6個團隊買菜,這樣子能使得情況變得不至於太糟糕。
這一點從目前來看只能是展望了,比如mysql資料庫換更為強大的oracle資料庫,
或更換InnoDb引擎為其他,或更換SATA硬碟為SSD 。。。。。。
相同的查詢條件,原來一個頁面查詢時間由於超過60秒超時了,根據1-6點建議優化之後,查詢時間變為2秒至3.5秒之間。
I. 對於多表關聯的,大數據分頁,怎麼整sql
可以做一個存儲過程,傳入參數的方式,參數可以有顯示第幾頁,分頁大小,可以返回總行數和查詢結果!