探討select in 在postgresql的效率問題
在知乎上看到這樣一個(gè)問題:
MySQL 查詢 select * from table where id in (幾百或幾千個(gè) id) 如何提高效率?修改
電商網(wǎng)站,一個(gè)商品屬性表,幾十萬條記錄,80M,索引只有主鍵id,做這樣的查詢?nèi)绾翁岣咝剩?br />
select * from table where id in (幾百或幾千個(gè)id)
這些id沒啥規(guī)律,分散的。。。。
看了一下答案,感覺有好多不靠譜的,但是口說無憑,所以在我的電腦上寫了幾個(gè)查詢測(cè)試一下。我用的是Postgresql9.4,但感覺mysql應(yīng)該也差不多,首先創(chuàng)建一個(gè)簡單表,只有簡單的3列,在這個(gè)問題的下面好多人提到了需要看表的大小,其實(shí)這個(gè)問題和表大小無關(guān),只和index的大小有關(guān),因?yàn)槭莍ndex是建立在int上的,所以只和紀(jì)錄數(shù)目有關(guān)。
Table "public.t9" Column | Type | Modifiers --------+----------------+----------- c1 | integer | c2 | character(100) | c3 | character(200) | Indexes: "i1" UNIQUE, btree (c1)insert into t9 values(generate_series(1000,500000,1),repeat('a',90),repeat('b',180));
之后生成一些隨機(jī)數(shù),Mac上用jot,Linux上用shuf
for ((i=0;i<100000;i++)) do jot -r 1 1000 600000 >>rand.file done
然后根據(jù)rand.file 生成查詢語句:
select * from t9 where c1 in ( 494613, 575087, 363588, 527650, 251670, 343456, 426858, 202886, 254037, ... 1 );
分別生成3個(gè)sql文件,in內(nèi)變量的數(shù)目分別是100,1000和10000個(gè),執(zhí)行這3個(gè)sql文件,看看時(shí)間
try psql study -f test_100.sql -o /dev/null LOG: duration: 2.879 ms try psql study -f test_1000.sql -o /dev/null LOG: duration: 11.974 ms try psql study -f test_10000.sql -o /dev/null LOG: duration: 355.689 ms
可以看到只有在in內(nèi)數(shù)據(jù)到了10,000個(gè)的時(shí)候數(shù)據(jù)時(shí)間會(huì)有比較大的變化,但也不過是在300多ms內(nèi)完成。
那如果按照有些回答那樣,先建一個(gè)臨時(shí)表,然后用in subquery,并且希望這時(shí)候可以兩表join呢?為了簡單我直接用兩表join了
drop table t_tmp; create table t_tmp(id int); insert into t_tmp (id) values (494613), (575087), (363588), (345980),... (1); select t9.* from t9, t_tmp where t9.c1 = t_tmp.id;
時(shí)間如何呢?
try psql study -f test_create_10000.sql -o /dev/null LOG: duration: 2.078 ms LOG: duration: 1.233 ms LOG: duration: 224.112 ms LOG: duration: 322.108 ms
除去drop和create的時(shí)間,依然花費(fèi)了500+的時(shí)間,這里的前提還是我用的ssd盤,所以寫LOG的時(shí)間會(huì)快很多。為什么會(huì)這么慢呢?用explain看一下,這時(shí)候數(shù)據(jù)量較大,直接走M(jìn)erge join 了
那1000行數(shù)據(jù)的效率如何呢?
try psql study -f test_create_1000.sql -o exp.out LOG: duration: 2.476 ms LOG: duration: 0.967 ms LOG: duration: 2.391 ms LOG: duration: 8.780 ms
100行的數(shù)據(jù)如下:
try psql study -f test_create_100.sql -o /dev/null LOG: duration: 2.020 ms LOG: duration: 1.028 ms LOG: duration: 1.074 ms LOG: duration: 1.912 ms
可以看到在100個(gè)值和1000個(gè)值的情況下create table的方式不會(huì)比直接在in里面寫所有的變量好多少,explain看的話是在用NLJ了。但在數(shù)據(jù)量更大(按照原問題,這里in的數(shù)量其實(shí)無法預(yù)知)的情況下效率只會(huì)更低,再加上額外的表維護(hù)成本和多余的SQL語句,DBA肯定不喜歡的,還是相信數(shù)據(jù)庫,放心大膽直接用in list來搞定這些問題吧。
以上內(nèi)容是針對(duì)select in 在postgresql的效率問題,希望對(duì)大家有所幫助!
相關(guān)文章
SQL Server 2005/2008 用戶數(shù)據(jù)庫文件默認(rèn)路徑和默認(rèn)備份路徑修改方法
本環(huán)境是SQL Server 2005 Standard Version 64-bit 和 SQL Server 2008 Standard Version 64-bit 雙實(shí)例同時(shí)安裝在一個(gè)2010-04-04
Windows Server 2008 Standard Version 64-bit OS上SQL Server服務(wù)啟動(dòng)的實(shí)現(xiàn)步驟
本文主要介紹了SQL Server服務(wù)啟動(dòng)的實(shí)現(xiàn)步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07SQLServer 2012中設(shè)置AlwaysOn解決網(wǎng)絡(luò)抖動(dòng)導(dǎo)致的提交延遲問題
這篇文章主要介紹了SQLServer 2012中設(shè)置AlwaysOn解決網(wǎng)絡(luò)抖動(dòng)導(dǎo)致的提交延遲問題,需要的朋友可以參考下2015-02-02sqlserver 巧妙的自關(guān)聯(lián)運(yùn)用
最近在改報(bào)表分頁,遇到一個(gè)很棘手的問題,需要將比較正常的數(shù)據(jù)記錄新增加兩列2012-07-07SQL Server 數(shù)據(jù)庫索引其索引的小技巧
關(guān)于索引的常識(shí):影響到數(shù)據(jù)庫性能的最大因素就是索引。由于該問題的復(fù)雜性,我只可能簡單的談?wù)勥@個(gè)問題,不過關(guān)于這方面的問題,目前有好幾本不錯(cuò)的書籍可供你參閱。我在這里只討論兩種SQL Server索引,即clustered索引和nonclustered索引2012-06-06SQL Server查找表名或列名中包含空格的表和列實(shí)例代碼
這篇文章主要給大家介紹了關(guān)于SQL Server如何查找表名或列名中包含空格的表和列的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起看看吧2018-09-09SQL Server 實(shí)現(xiàn)數(shù)字輔助表實(shí)例代碼
這篇文章主要介紹了SQL Server 實(shí)現(xiàn)數(shù)字輔助表的相關(guān)資料,并附實(shí)例代碼,需要的朋友可以參考下2016-10-10SQL?server插入報(bào)錯(cuò):當(dāng)?IDENTITY_INSERT?設(shè)置為?OFF?時(shí)不能為表?‘XXX‘?
這篇文章主要介紹了SQL?server插入報(bào)錯(cuò):當(dāng)?IDENTITY_INSERT?設(shè)置為?OFF?時(shí),不能為表?‘XXX‘?中的標(biāo)識(shí)列插入顯式值的問題,該問題是給SQL server數(shù)據(jù)庫中的某個(gè)表插入數(shù)據(jù)引起的報(bào)錯(cuò),一般出現(xiàn)在該表為自增的情況下,本文給大家分享解決方法,需要的朋友可以參考下2023-09-09詳解安裝sql2012出現(xiàn)錯(cuò)誤could not open key...解決辦法
這篇文章主要介紹了詳解安裝sql2012出現(xiàn)錯(cuò)誤could not open key...解決辦法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11