查詢中不使用表達式索引(正則表達式模式匹配)
在我的PostgreSQL 12.8數據庫中,我有一個相對簡單的表
the_table
,其中有一列value
類型為varchar
:CREATE TABLE public.the_table ( id uuid DEFAULT gen_random_uuid() NOT NULL, label character varying, value character varying, created_at timestamp without time zone NOT NULL, updated_at timestamp without time zone NOT NULL, );
我想查詢具有格式化為電子郵件地址的值的所有行。查詢如下所示:
SELECT * FROM the_table WHERE value ~ '^[a-zA-Z0-9.$%&*+/=?^_{|}~-]+@[a-zA-Z0-9.-]+\.[a-zA-Z0-9]+$'
.由於該表中有幾百萬行,我嘗試通過添加匹配的表達式索引來加速此查詢
CREATE INDEX index_the_table_on_email_values ON the_table ((value ~ '^[a-zA-Z0-9.$%&*+/=?^_{|}~-]+@[a-zA-Z0-9.-]+\.[a-zA-Z0-9]+$'));
不幸的是,查詢計劃器不使用索引,而是對錶執行全盤掃描,這非常慢。
誰能幫我修復索引或告訴我還有哪些其他選擇?我已經考慮過生成的布爾列
is_email
。我可以向該生成的列添加索引並直接查詢它。但這似乎是原始問題的一種奇怪的解決方法,應該可以通過匹配索引來解決,對嗎?
公平地說,您對
boolean
錶達式的索引基本上也有效。關鍵是:如果有很大比例的“電子郵件”行,那麼沒有索引會幫助(很多)——除了特殊情況。Postgres 通常會選擇更快的順序掃描。(我懷疑這是你的情況。)
如果只有很少的“電子郵件”行,那麼部分索引會更有效,因為它排除了大多數行開頭:
CREATE INDEX the_table_email_idx ON the_table ((true)) WHERE value ~ '^[a-zA-Z0-9.$%&*+/=?^_{|}~-]+@[a-zA-Z0-9.-]+\.[a-zA-Z0-9]+$';
(true)
只是一個任意常數,因為沒有明顯的索引列。通常,您在“電子郵件過濾器”頂部有一個有用的索引列,可以替換該常量 - 使索引更加有用。有關的:當然,生成列
is_email
的想法也不錯。然後,您將使用該生成列上的條件創建部分索引。這有好處也有壞處。