今天在itput上看了一篇文章,是討論乙個語句的優化:
優化的語句:
請問以下語句如何優化:
create
table
aa_001
( ip
varchar2(28
), name
varchar2(10
), password
varchar2(30
) )
select
*from
aa_001
where
ip in(1
,2,3
) order
byname
desc;--
目前表中記錄有一千多萬條左右,而且in中的值個數是不確定的。
以上就是優化的需要優化的語句和情況。
不少人在後面跟帖:有的說沒辦法優化,有的說將in該為exists,有的說在ip上建立索引復合索引(ip,name)等等。
那這樣的情況,能優化嗎,如何優化?今天就來討論這個問題。
1,資料量1千萬多條。
2,in中的值個數是不確定
3.1 分析資料分布
這裡作者沒有提到ip列的資料的分布情況,目前ip列的資料分布可能有以下幾種:
1,ip列(資料唯一,或者資料重複的概率很小)
2,ip列 (資料不均勻,可能有些資料重複多,有些重複少)
3,ip列 (資料分布比較均勻,資料大量重複,主要就是一些同樣的資料(可能只有上萬級別不同的ip資料等)
解決問題:
1,對於第一種資料分布情況,只要在ip列建立乙個索引即可。這時不管表有多少行, in個數是不確定的情況下,都很快。
2,對應第二中資料分布情況,在ip列建立索引,效果不好。因為資料分布不均勻,可能有些快,有些慢
3,對應第三種資料分布情況,在ip列建立索引,速度肯定慢。
注意:這裡的 order by name desc 是在取出資料後再排序的。而不是取資料前排序
對於2,3兩個情況,因為都是可能需要取出大量的資料,優化器就採用表掃瞄(table scan),而不是索引查詢(index seek) ,速度很慢,因為這時表掃瞄效率要優於索引查詢,特別是高併發情況下,效率很低。
那對應2,3中情況,如何處理。是將in改成exists。其實在sql server 2005和oracle裡的優化器在in後面資料少時,效率是一樣的。這時採用一般的索引效率很低。這時如果在ip列上建立聚集索引,效率會比較高。我們在sql server 2005中做個測試。
表:[dbo].[[zping.com]]]中有約200萬條資料。包含列userid, id, ruleid等列。按照上面的情況查詢一下類似語句:
select
*from
[dbo].
[[zping.com
]]]
where
userid in(
'402881410ca47925010cb329c7670ffb',
'402881ba0d5dc94e010d5dced05a0008',
'4028814111a735e90111a77fa8e30384')
order
byruleid
desc
我們先看userid的資料分布情況,執行下面語句:
select
userid,
count(*
) from
[dbo].
[[zping.com
]]]
group
byuserid
orderby2
這時我們看看資料分布:總共有379條資料,資料兩從1到15萬都有,資料分布傾斜嚴重。下圖是其中一部分。
這時如果在ip上建立非聚集索引,效率很低,而且就是強行索引掃瞄,效率也很低,會發現io
次數比表掃瞄還高。這時只能在ip上建立聚集索引。這時看看結果。
這時發現,搜尋採用了(clustered index seek)聚集搜尋掃瞄。
在看看查詢返回的結果:
(156603
行受影響)表 '
[zping.com]
'。掃瞄計數
8,邏輯讀取
5877
次,物理讀取
0次,預讀
0次,lob 邏輯讀取
0次,lob 物理讀取
0次,lob 預讀 0次。
表 'worktable
'。掃瞄計數
0,邏輯讀取
0次,物理讀取
0次,預讀
0次,lob 邏輯讀取
0次,lob 物理讀取
0次,lob 預讀 0次。
返回15萬行,才不到6千次io。效率較高,因為這15萬行要排序,查詢成本裡排序佔了51%。當然可以建立(userid,ruleid)復合聚集索引,提高效能,但這樣做dml維護成本較高。建議不採用。
從上面的測試例子可以看出, 優化的解決辦法:
資料分布為1:建立ip索引即可
資料分布為2,3:在ip列建立聚集索引。
SQL大資料量分頁效能優化
目前在進行web api唯讀介面的改造,在改造過程中,發現改在後響應時間和之前區別不是很大,通過測試結果顯示在sql的分頁功能處找到原因,並對其進行優化,優化方案如下。測試內容 此次執行時間對比採用平台資金記錄最多的使用者 user id 36062 測試次數未5次 為避免索引快取每次測試前更改 l...
大資料量分頁優化
用limit offset 時並不是先跳過再查詢 而是 先查詢,再跳過 limit 100w,10 先把100w取出來,然後跳過前100w行,所以大資料分頁用limit很慢 select id,name from lx com 5000000,10 先查詢出來5000000 select id,na...
MySQL大資料量分頁SQL語句優化
分頁程式原理很簡單,這裡就不多說了,本篇文章主要說的是在資料表記錄量比較大的情況下,如何將分頁sql做到更優化,讓mysql執行的更快的方法。一般的情況下,我們的分頁sql語句是這樣的 檢視 列印 1select fromtableorderbyid limit 1000,10 以上sql語句在原理...