Przeczytałem o indeksach funkcjonalnych i skanach zindeksowanych w dokumencie/wiki opublikowanym przez Postgres.Postgres Indeks skanowania 9,6 tylko na indeks funkcjonalny jest logicznie możliwy, ale nie został wykonany
teraz mam zapytanie jak:
SELECT(xpath('/document/uuid/text()', xmldata))[1]::text,
(xpath('/document/title/text()', xmldata))[1]::text
FROM xmltable
WHERE(xpath('/document/uuid/text()', xmldata))[1]::text = 'some-uuid-xxxx-xxxx'
i indeksie:
CREATE INDEX idx_covering_index on xmltable using btree (
((xpath('/document/uuid/text()', xmldata))[1]::text),
((xpath('/document/title/text()', xmldata))[1]::text)
)
Indeks ten, patrząc na to logicznie, wskaźnik pokrycia i powinna umożliwić indeks-Only-skan , ponieważ wszystkie żądane wartości są zawarte w indeksie (uuid i title)
Teraz wiem, że Postgres rozpoznaje tylko indeksy obejmujące indeksy funkcjonalne, jeśli kolumny używane w functio N- połączenia są również zawarte
np .:
SELECT to_upper(column1) from table where id >10
1) nie może być pokryte przez tę index:
CREATE INDEX idx_covering_index on xmltable using btree (id, to_upper(column1));
2), ale może być pokryta tego:
CREATE INDEX idx_covering_index on xmltable using btree (column1, id, to_upper(column1));
co prowadzi do skanowania tylko do indeksu.
Gdybym teraz spróbuj to z mojej konfiguracji XML:
CREATE INDEX idx_covering_index on xmltable using btree (xmldata,
((xpath('/document/uuid/text()', xmldata))[1]::text),
((xpath('/document/title/text()', xmldata))[1]::text)
)
pojawia się błąd:
data type xml has no default operator class for access method "btree"
uczciwą tyle, niestety zwykle używany "text_ops"
lub "text_pattern_ops"
nie akceptują "xml" jako input - w ten sposób renderując mój indeks - choć obejmowałby on wszystkie wartości - nie może obsługiwać skanów tylko z indeksem.
Czy można to obsłużyć w sposób umożliwiający skanowanie tylko do indeksu?
@ Edit1:
wiem, że postgres nie może użyć indeksu widziany w 1) pokrycie indeksu, ale można użyć indeksu jak 2)
Próbowałem też z bardzo prostych tabel w celu sprawdzenia tego zachowania , i ja też pamiętam, że to przeczytałem - ale nie mogę o tym pamiętać.
create table test (
id serial primary key,
quote text
)
insert into test (number, quote) values ('I do not know any clever quotes');
insert into test (number, quote) values ('I am sorry');
CREATE INDEX idx_test_functional on test using btree ((regexp_replace(quote, '^I ', 'BillDoor ')));
set enable_seqscan = off;
analyze test;
explain select quote from test where regexp_replace(quote, '^I ', 'BillDoor ') = 'BillDoor do not know any clever quotes'
--> "Index Scan using idx_test_functional on test (cost=0.13..8.15 rows=1 width=27)"
drop index idx_test_functional;
CREATE INDEX idx_test_functional on test using btree (quote, (regexp_replace(quote, '^I ', 'BillDoor ')));
analyze test;
explain select quote from test where regexp_replace(quote, '^I ', 'BillDoor ') = 'BillDoor do not know any clever quotes'
--> "Index Only Scan using idx_test_functional on test (cost=0.13..12.17 rows=1 width=27)"
@ Edit2:
pełną definicję tabeli xmltable:
id serial primary key (clustered),
xmldata xml (only data used to filter queries)
history xml (never queried or read, just kept in case of legal inquiry)
fileinfo text (seldom quieried, sometimes retrieved)
"timestamp" timestamp (mainly for legal inquiries too)
tabeli zawiera ok .: 500.000 Rekordy, xmldata ma rozmiar od 350 do 800 bajtów, historia jest znacznie większa, ale rzadko pobierana i nigdy nie jest używana w filtrach
Dla pewności, że uzyskałem prawdziwe wyniki, zawsze po uruchomieniu lub porzuceniu uruchomiłem analyze xmltable
indeks
pełny plan wykonania dla zapytania:
explain analyze select (xpath('/document/uuid/text()', d.xmldata))[1]::text as uuid
from xmltable as d
where
(xpath('/document/uuid/text()', d.xmldata))[1]::text = 'some-uuid-xxxx-xxxx' and (xpath('/document/genre/text()', d.xmldata))[1]::text = 'bio'
objętym niniejszym indizies:
create index idx_genre on xmltable using btree (((xpath('/document/genre/text()', xmldata))[1]::text));
create index idx_uuid on xmltable using btree (((xpath('/document/uuid/text()', xmldata))[1]::text));
create index idx_uuid_genre on xmltable using btree (((xpath('/document/uuid/text()', xmldata))[1]::text), ((xpath('/document/genre/text()', xmldata))[1]::text));
pierwszy lea DS:
"Index Scan using idx_genre on xmldata d (cost=0.42..6303.05 rows=18154 width=32)"
" Index Cond: (((xpath('/document/genre/text()'::text, xmldata, '{}'::text[]))[1])::text = 'bio'::text)"
" Filter: (((xpath('/document/uuid/text()'::text, xmldata, '{}'::text[]))[1])::text = 'some-uuid-xxxx-xxxx'::text)"
sprawiedliwe tyle myślałem, po prostu do testowania będę zmuszać go używać - w moim umyśle - indeks obejmujący:
drop index idx_uuid;
drop index idx_genre;
i teraz uzyskać:
"Bitmap Heap Scan on xmltable d (cost=551.13..16025.51 rows=18216 width=32)"
" Recheck Cond: ((((xpath('/document/genre/text()'::text, xmldata, '{}'::text[]))[1])::text = 'bio'::text) AND (((xpath('/document/uuid/text()'::text, xmldata, '{}'::text[]))[1])::text = 'some-uuid-xxxx-xxxx'::text))"
" -> Bitmap Index Scan on idx_uuid_genre (cost=0.00..546.58 rows=18216 width=0)"
" Index Cond: ((((xpath('/document/genre/text()'::text, xmldata, '{}'::text[]))[1])::text = 'bio'::text) AND (((xpath('/document/uuid/text()'::text, xmldata, '{}'::text[]))[1])::text = 'some-uuid-xxxx-xxxx'::text))"
Próbowałem także przełączać pozycje uuid i gatunek w indeksie, ten sam plan wykonania.
'Teraz już wiem, że postgres rozpoznaje tylko ukryte indizje na funkcjonalnych indiziach, jeśli kolumny użyte w wywołaniach funkcjonalnych są również zawarte. Czy możesz podać jakiekolwiek odniesienie do dokumentacji wspierającej to; to bardzo sprzeczne z intuicją. To jest ... jak "teraz wiesz". –
Jaka jest pełna definicja tabeli 'xmltable'? Jaki jest plan wykonania instrukcji, jeśli indeks jest obecny? Czy Postgres korzysta z indeksu do wyszukiwania indeksu, czy w ogóle nie korzysta z tego indeksu? –
Wiem, bo próbowałem zi bez xml, zwykłe tabele, json itp. Wydało mi się to również dziwne - będę edytować pytanie, aby dołączyć to – billdoor