Portál AbcLinuxu, 10. května 2025 12:42
sl1 sl2 1 --xDas 2 a-xas 3 --x--Udělat to pomocí LIKE trvá strašně dlouho, proto bych rád věděl, zda to jde udělat indexovaně? Je mi víceméně jedno jestli se bude hledat třeba podle sloupce typu VARCHAR či např. podle INTu, kde by se hledalo binární operací AND, ale potřebuju na to vytvořit a používat indexy. Jak na to?
CREATE TABLE foo(s text); CREATE INDEX ON foo USING GIN ((substring(s FROM 1 FOR 1)); CREATE INDEX ON foo USING GIN ((substring(s FROM 2 FOR 1)); CREATE INDEX ON foo USING GIN ((substring(s FROM 3 FOR 1)); SELECT * FROM foo WHERE substring(s FROM 3 FOR 1) = 'x';tahle podminka bude mit dost mizernou selectivitu - dost mozna ze problem je jenom v like a stacilo by nepouzivat like
SELECT * FROM foo WHERE substring(s FROM 3 FOR 1) = 'x';Jeste by slo pouzit hstore:
postgres=# create or replace function pack(text) returns hstore as $$ SELECT string_agg(i || '=>' || substring($1 FROM i FOR 1),',')::hstore FROM generate_series(1,length($1)) g(i); $$ LANGUAGE sql IMMUTABLE; CREATE FUNCTION postgres=# select pack('Pavel'); pack -------------------------------------------------- "1"=>"P", "2"=>"a", "3"=>"v", "4"=>"e", "5"=>"l" (1 row) postgres=# select * from xx; a ------- Pavel (1 row) postgres=# CREATE INDEX ON xx USING GIN((pack(a))); CREATE INDEX postgres=# SELECT * FROM xx WHERE pack(a) @> '3=>v'; a ------- Pavel (1 row) postgres=# set enable_seqscan to off; SET postgres=# explain SELECT * FROM xx WHERE pack(a) @> '3=>v'; QUERY PLAN --------------------------------------------------------------------------- Bitmap Heap Scan on xx (cost=12.25..16.51 rows=1 width=32) Recheck Cond: (pack(a) @> '"3"=>"v"'::hstore) -> Bitmap Index Scan on xx_pack_idx (cost=0.00..12.25 rows=1 width=0) Index Cond: (pack(a) @> '"3"=>"v"'::hstore) (4 rows) postgres=# SELECT * FROM xx WHERE pack(a) @> '3=>v, 4=>e'; a ------- Pavel (1 row) postgres=# SELECT * FROM xx WHERE pack(a) @> '3=>v, 4=>x'; a --- (0 rows)Ale co bude rychlejsi netusim - hstore je hodne genericky, takze pokud by tam byla nizka selectivita, tak by to nemuselo byt efektivni
Souhlas... a nebo jít cestou oindexování volání funkce - viz CREATE INDEX, je tam příklad na vytvoření indexu nad lower()
Tak spojeni velkych tabulek muze byt vypocetne velice narocne, to neni zadny mytus, zalezi na konkretni situaci.Je to mýtus. Spojení velkých tabulek nic nestojí. Nákladné je vyhledávání. Zkuste si to. Udělejte si SELECT na spojení tabulek, a pak soustavu SELECTů, která vybere ta samá data bez spojení v databázi (spojení uděláte v aplikaci). To druhé bude pomalejší – hledání použije stejné indexy, ale v druhém případě bude víc režie se spojením, parsováním dotazů apod.
SELECT A.* FROM table1 A JOIN table2 B ON (A.id = B.a_id) WHERE A.id = 1 SELECT A.* FROM table1 A WHERE A.id = 1
Tiskni
Sdílej:
ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.