Temat: MS SQL (lub PostgreSQL) i wyszukiwanie po polu...
Wszystko zależy od indeksów.
Jak jest indeks na kolumnie id:
"i2_b_16" btree (id) WHERE (flag & 16) = 16
"i2_b_32" btree (id) WHERE (flag & 32) = 32
to wtedy plan wygląda tak:
# explain analyze select * from flag_test2 where flag&16=16 and flag&32=32;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------
Index Scan using i2_b_32 on flag_test2 (cost=0.00..2031.42 rows=250 width=8) (actual time=139.363..139.363 rows=0 loops=1)
Filter: ((flag & 16) = 16)
Rows Removed by Filter: 156521
Total runtime: 139.404 ms
(4 rows)
Natomiast gdy indeksy będą wyglądały tak:
"i_b_16" btree (flag) WHERE (flag & 16) = 16
"i_b_32" btree (flag) WHERE (flag & 32) = 32
To plan wygląda tak:
# explain analyze select * from flag_test where flag&16=16 and flag&32=32;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------
Bitmap Heap Scan on flag_test (cost=1614.54..2563.16 rows=250 width=8) (actual time=1377.525..1377.525 rows=0 loops=1)
Recheck Cond: (((flag & 32) = 32) AND ((flag & 16) = 16))
Rows Removed by Index Recheck: 7442859
-> BitmapAnd (cost=1614.54..1614.54 rows=250 width=0) (actual time=335.878..335.878 rows=0 loops=1)
-> Bitmap Index Scan on i_b_32 (cost=0.00..806.42 rows=50000 width=0) (actual time=24.063..24.063 rows=156521 loops=1)
-> Bitmap Index Scan on i_b_16 (cost=0.00..807.74 rows=50000 width=0) (actual time=309.127..309.127 rows=5002763 loops=1)
Total runtime: 1377.591 ms
(7 rows)
I jeszcze rozkład danych:
# select count(*) from flag_test;
count
----------
10000000
# select count(*) from flag_test where (flag & 16) = 16;
count
---------
5002763
(1 row)
# select count(*) from flag_test where (flag & 32) = 32;
count
--------
156521
# select count(*) from flag_test where (flag & 32) = 32 and (flag & 16) = 16;
count
-------
0
Jak widać użycie jednego indeksu wcale nie musi oznaczać, że to będzie wolniejsze, niż użycie dwóch indeksów :)
PostgreSQL używa tego indeksu, który daje większą selektywność, a potem sprawdza drugi warunek.
Szymon G. edytował(a) ten post dnia 10.12.12 o godzinie 13:06