5

目前,我有以下幾點:更快地搜索字段第一個字符不匹配的記錄[A-Za-z]?

User (id, fname, lname, deleted_at, guest) 

我可以像這樣通過他們fname初始查詢用戶的列表:

User Load (9.6ms) SELECT "users".* FROM "users" WHERE (users.deleted_at IS NULL) AND (lower(left(fname, 1)) = 's') ORDER BY fname ASC LIMIT 25 OFFSET 0 

這是快速感謝以下指標:

CREATE INDEX users_multi_idx 
    ON users (lower(left(fname, 1)), fname) 
    WHERE deleted_at IS NULL; 

我想現在要做的就是能夠查詢對於不以字母的AZ開頭的所有用戶。我得到這個像這樣的工作:

SELECT "users".* FROM "users" WHERE (users.deleted_at IS NULL) AND (lower(left(fname, 1)) ~ E'^[^a-zA-Z].*') ORDER BY fname ASC LIMIT 25 OFFSET 0 

但問題是,這個查詢很慢,似乎並沒有被使用索引,以加快第一個查詢。有關如何優雅地使第二個查詢(非a-z)更快的建議?

我使用的Postgres 9.1與3.2的軌道

感謝

+0

感謝您展示您的版本。如果您將兩個查詢的'EXPLAIN ANALYZE'粘貼到http://explain.depesz,可能會有所幫助。com /並且在這裏與他們相關聯(你應該爲所有性能問題做這件事),儘管在這種情況下,第一個是使用第二個不能的索引是合理的。 –

+1

請將它們鏈接到以前的相關問題,它有助於使答案更容易。 –

回答

3

更新答案
Preceding question here.

我的第一個思想觀念(指數與text_pattern_ops)沒有用正則表達式工作我的測試。查詢更好改寫爲:

SELECT * 
FROM users 
WHERE deleted_at IS NULL 
WHERE lower(left(fname, 1)) < 'a' COLLATE "C" OR lower(left(fname, 1)) > 'z' COLLATE "C" 
ORDER BY fname 
LIMIT 25 OFFSET 0;

除了從這些表達式是通常速度更快,你的正則表達式也有它大寫字母,它沒有索引與lower()匹配。與單個字符相比,尾隨字符毫無意義。

,並使用此指數:

CREATE INDEX users_multi_idx 
ON users (lower(left(fname, 1)) COLLATE "C", fname) 
WHERE deleted_at IS NULL;

COLLATE "C"部分是可選的,不僅有助於在性能上非常小的增益。它的目的是將歸類規則重置爲默認的posix歸類,它僅使用字節順序,並且通常更快。有用的是,排序規則無論如何都不相關。

如果您使用它創建索引,則只有符合排序規則的查詢才能使用它。因此,如果性能不是您的首要要求,您可能會跳過來簡化事情。

+1

必須是'OR',而不是'AND',當然。 –

+0

謝謝,但結果w錯誤:ActionView :: Template :: Error(PG :: Error:ERROR:column「a」does not exist LINE 1:... deleted_at IS NULL)AND(lower(left(fname, 1))<「a」COLLAT ... – AnApprentice

+1

@ColdTree:用單引號替換「a」周圍的雙引號: - > **''a'' **。 –

2

作爲替代@ ErwinBrandstetter的一般的解決方案,PostgreSQL支持partial indexes。你可以這樣說:

CREATE INDEX users_nonalphanumeric_not_deleted_key 
ON users (id) 
WHERE (users.deleted_at IS NULL) AND (lower(left(fname, 1)) ~ E'^[^a-zA-Z].*'); 

這個索引不會幫助任何其他查找,但它會預先計算這個特定查詢的答案。此技術對於從更大的表中返回小的預定義子集的查詢通常很有用,因爲結果索引將忽略絕大多數表並僅包含感興趣的行。

+2

請注意,您的查詢將需要幾乎逐字地使用索引條件;查詢計劃人員在匹配等效條件方面不太聰明。例如,如果您顛倒了'AND'這兩個子句,則規劃者可能不會使用該索引。我發現將索引條件包裝在一個SQL函數中很有用,然後在我想引用索引的地方使用該SQL函數,因爲這使得規劃人員很容易匹配這兩者。 –

相關問題