我已閱讀Postgres發佈的docs/wiki中的功能索引和僅索引掃描。postgres 9.6索引只掃描功能索引邏輯上可能但未執行
我現在有這樣一個查詢:
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'
和索引:
CREATE INDEX idx_covering_index on xmltable using btree (
((xpath('/document/uuid/text()', xmldata))[1]::text),
((xpath('/document/title/text()', xmldata))[1]::text)
)
這個指標是,看它在邏輯上,一個覆蓋索引,應啓用僅索引掃描,因爲所有查詢的值都包含在索引中(uuid和title)
我現在碰巧知道,Postgres只能識別函數索引的覆蓋索引,如果函數中使用的列正呼叫也包含
例如:
SELECT to_upper(column1) from table where id >10
1)不能由該索引覆蓋:
CREATE INDEX idx_covering_index on xmltable using btree (id, to_upper(column1));
2),但可以通過這一個覆蓋:
CREATE INDEX idx_covering_index on xmltable using btree (column1, id, to_upper(column1));
因此導致僅索引掃描。
如果我現在就來試試這跟我的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)
)
我得到一個錯誤:
data type xml has no default operator class for access method "btree"
合理,不幸的是,通常使用"text_ops"
或"text_pattern_ops"
不接受 「XML」 作爲輸入 - 因此呈現我的索引 - 雖然它會覆蓋所有值 - 不能支持僅索引掃描。
這是否可以通過一種方式進行處理,從而爲索引掃描提供可能性?
@ EDIT1:
我知道的Postgres不能用作爲覆蓋指數在1看到的指數),但可以像使用2索引)
我也試圖與非常簡單的表來驗證此行爲,我還記得有這樣的閱讀 - 但我不能爲我的生活記得在哪裏。
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: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)
表中包含約:500。000條記錄,xmldata的大小在350到800字節之間,歷史要大得多,但很少被檢索到,並且從未用於過濾器
爲了記錄,當然要得到真正的結果,我總是在創建或刪除後運行analyze xmltable
索引
用於查詢的完整執行計劃:
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'
由這些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));
第一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)"
公平足夠我想,只是爲了測試我會強制其使用 - 在我的腦海 - 覆蓋指數:
drop index idx_uuid;
drop index idx_genre;
,現在我得到:
"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))"
我也嘗試在索引,相同的執行計劃中切換uuid和流派的位置。
'我現在碰巧知道,如果函數調用中使用的列也包含在內,那麼postgres只承認在函數式indizies上覆蓋indizies,您能提供對支持這些函數的文檔的任何參考;這非常直觀。那是......你現在怎麼知道。 –
表「xmltable」的完整定義是什麼?如果指數存在,那麼聲明的執行計劃是什麼? Postgres是否將索引用於索引查找,還是根本不使用該索引? –
我知道,因爲我嘗試過使用和不使用xml,普通表,json等等。它對我來說似乎也很奇怪 - 我將編輯這個問題來追加這個 – billdoor