Chr*_*itt 5 postgresql performance index postgresql-performance
目前,我有一个定义如下的视图:
View "public.customer_list"
Column | Type | Modifiers | Storage | Description
-----------+-------------------------+-----------+----------+-------------
id | bigint | | plain |
name | character varying(100) | | extended |
street | character varying(100) | | extended |
zip | character varying(10) | | extended |
city | character varying(100) | | extended |
country | character varying(3) | | extended |
phone | character varying(100) | | extended |
mail | character varying(100) | | extended |
rating | integer | | plain |
salesnote | character varying(1800) | | extended |
View definition:
SELECT c.id,
c.name,
a.street,
a.zip,
a.city,
a.country,
c.phone,
c.mail,
c.rating,
c.salesnote
FROM crm_customer c
JOIN crm_address a ON a.id = c.address_id;
Run Code Online (Sandbox Code Playgroud)
为了更好地搜索列表,我创建了一个索引,如下所示:
CREATE INDEX crm_customer_big_index
ON crm_customer (name ASC,
name text_pattern_ops,
(id::text) text_pattern_ops,
phone text_pattern_ops,
mail text_pattern_ops,
rating);
Run Code Online (Sandbox Code Playgroud)
我用不同的 where 查询来搜索这个表,主要是这样的:
SELECT *
FROM customer_list
WHERE lower(name::text) LIKE 'env%'
AND rating = 3
ORDER BY name ASC
LIMIT 20
OFFSET 0;
Run Code Online (Sandbox Code Playgroud)
但是我的分析器仍然不会使用索引。有没有办法使用一个?
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=164.04..164.08 rows=15 width=129) (actual time=3.243..3.244 rows=1 loops=1)
-> Sort (cost=164.04..164.08 rows=15 width=129) (actual time=3.243..3.243 rows=1 loops=1)
Sort Key: c.name
Sort Method: quicksort Memory: 26kB
-> Nested Loop (cost=0.28..163.75 rows=15 width=129) (actual time=0.020..3.225 rows=1 loops=1)
-> Seq Scan on crm_customer c (cost=0.00..111.13 rows=15 width=98) (actual time=0.012..3.216 rows=1 loops=1)
Filter: ((rating = 3) AND (lower((name)::text) ~~ 'env%'::text))
Rows Removed by Filter: 2978
-> Index Only Scan using crm_address_search_index on crm_address a (cost=0.28..3.50 rows=1 width=47) (actual time=0.006..0.006 rows=1 loops=1)
Index Cond: (id = c.address_id)
Heap Fetches: 0
Planning time: 0.580 ms
Execution time: 3.286 ms
Run Code Online (Sandbox Code Playgroud)
目前,查询仍然“有点”快。但是,我的表中可以有更多数据。此外,crm_address有一个索引 over street, zip, city, country,它工作正常。
表达lower(name::text)是不属于你的指数,这也似乎没有有用所有,至少我们在你的问题中看到的:
CREATE INDEX crm_customer_big_index
ON crm_customer (name ASC,
name text_pattern_ops,
(id::text) text_pattern_ops,
phone text_pattern_ops,
mail text_pattern_ops,
rating);
Run Code Online (Sandbox Code Playgroud)
该索引将涵盖您的查询:
CREATE INDEX crm_customer_foo_index ON crm_customer (
rating
, lower(name::text) text_pattern_ops
, address_id); -- for the join
Run Code Online (Sandbox Code Playgroud)
为了优化,我建议另外调整您的查询:
SELECT *
FROM customer_list
WHERE lower(name::text) LIKE 'env%'
AND rating = 3
ORDER BY lower(name::text), name
LIMIT 20;Run Code Online (Sandbox Code Playgroud)
此外,如果您只对 的前几个字符感兴趣,name character varying(100)只需索引前几个字符,即可使索引更短更快:
CREATE INDEX crm_customer_foo_index ON crm_customer (
rating
, lower(left(name::text, 7)) text_pattern_ops -- example with local optimum
, address_id); -- for the join
Run Code Online (Sandbox Code Playgroud)
查询必须匹配索引表达式:
WHERE lower(left(name::text, 7)) LIKE 'env%'
...
ORDER BY lower(left(name::text, 7)), name
Run Code Online (Sandbox Code Playgroud)
不确定风景是否以某种方式挡住了视线。但它应该是透明的。
我根本不会用varchar(n)。只是text:
关于模式匹配和text_pattern_ops:
为什么我把rating索引放在第一位?
有一些查询技术可以更好地利用非前导索引列。考虑Postgres Wiki 上的 "Loose indexscan"。
| 归档时间: |
|
| 查看次数: |
1001 次 |
| 最近记录: |