在知乎上看到這樣一個問題:
MySQL 查詢 select * from table where id in (幾百或幾千個 id) 如何提高效率?修改
電商網(wǎng)站,一個商品屬性表,幾十萬條記錄,80M,索引只有主鍵id,做這樣的查詢?nèi)绾翁岣咝剩?br />
select * from table where id in (幾百或幾千個id)
這些id沒啥規(guī)律,分散的。。。。
看了一下答案,感覺有好多不靠譜的,但是口說無憑,所以在我的電腦上寫了幾個查詢測試一下。我用的是Postgresql9.4,但感覺mysql應(yīng)該也差不多,首先創(chuàng)建一個簡單表,只有簡單的3列,在這個問題的下面好多人提到了需要看表的大小,其實這個問題和表大小無關(guān),只和index的大小有關(guān),因為是index是建立在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));
之后生成一些隨機數(shù),Mac上用jot,Linux上用shuf
for ((i=0;i100000;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個sql文件,in內(nèi)變量的數(shù)目分別是100,1000和10000個,執(zhí)行這3個sql文件,看看時間
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個的時候數(shù)據(jù)時間會有比較大的變化,但也不過是在300多ms內(nèi)完成。
那如果按照有些回答那樣,先建一個臨時表,然后用in subquery,并且希望這時候可以兩表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;
時間如何呢?
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的時間,依然花費了500+的時間,這里的前提還是我用的ssd盤,所以寫LOG的時間會快很多。為什么會這么慢呢?用explain看一下,這時候數(shù)據(jù)量較大,直接走Merge 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個值和1000個值的情況下create table的方式不會比直接在in里面寫所有的變量好多少,explain看的話是在用NLJ了。但在數(shù)據(jù)量更大(按照原問題,這里in的數(shù)量其實無法預(yù)知)的情況下效率只會更低,再加上額外的表維護成本和多余的SQL語句,DBA肯定不喜歡的,還是相信數(shù)據(jù)庫,放心大膽直接用in list來搞定這些問題吧。
以上內(nèi)容是針對select in 在postgresql的效率問題,希望對大家有所幫助!
您可能感興趣的文章:- input+select(multiple) 實現(xiàn)下拉框輸入值
- 在Spring中用select last_insert_id()時遇到問題
- 解決IE下select標(biāo)簽innerHTML插入option的BUG(兼容IE,FF,Opera,Chrome,Safari)
- Mysql select in 按id排序?qū)崿F(xiàn)方法
- 解析MySQL中INSERT INTO SELECT的使用
- insert into select和select into的使用和區(qū)別介紹
- linux使用select實現(xiàn)精確定時器詳解
- 解決Hibernate JPA中insert插入數(shù)據(jù)后自動執(zhí)行select last_insert_id()
- 數(shù)據(jù)庫插入數(shù)據(jù)之select into from與insert into select區(qū)別詳解
- PostgreSQL教程(六):函數(shù)和操作符詳解(2)
- PostgreSQL教程(七):函數(shù)和操作符詳解(3)
- PostgreSQL教程(十六):系統(tǒng)視圖詳解