以下查询在Postgres上运行
SELECT COUNT(*)
FROM "posts"
WHERE "posts"."author_id" = 20
AND ("posts"."title" ILIKE '123');
显然涉及到一个非常慢的位图堆扫描。我怎样才能诊断为什么这么慢?我能做些什么让它表现更好?
my-app::DATABASE=> EXPLAIN ANALYZE VERBOSE
my-app::DATABASE-> SELECT COUNT(*)
my-app::DATABASE-> FROM "posts"
my-app::DATABASE-> WHERE "posts"."author_id" = 20
my-app::DATABASE-> AND ("posts"."title" ILIKE '123');
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------------------------------------
Aggregate (cost=25516.64..25516.64 rows=1 width=0) (actual time=35632.267..35632.267 rows=1 loops=1)
Output: count(*)
-> Bitmap Heap Scan on public.posts (cost=307.46..25516.64 rows=1 width=0) (actual time=35632.264..35632.264 rows=0 loops=1)
Recheck Cond: (posts.author_id = 20)
Filter: ((posts.title)::text ~~* '123'::text)
Rows Removed by Filter: 22216
Heap Blocks: exact=15419
-> Bitmap Index Scan on index_posts_on_author_id_and_state (cost=0.00..307.46 rows=23586 width=0) (actual time=54.585..54.585 rows=22235 loops=1)
Index Cond: (posts.author_id = 20)
Planning time: 0.853 ms
Execution time: 35632.405 ms
(11 rows)
答案 0 :(得分:2)
编写查询的方式,没有索引可以使它更好。
但你可以像这样重写它:
SELECT count(*)
FROM posts
WHERE posts.author_id = 20
AND lower(posts.title) LIKE lower('abc%');
然后,以下索引可以在某些情况下帮助 :
CREATE INDEX posts_auth_title_ind
ON posts (
author_id,
lower(title) text_pattern_ops
);
除非您使用text_pattern_ops
或LIKE
归类,否则C
需要 POSIX
。
如果搜索模式以通配符开头,则没有B树索引可以提供帮助。在这种情况下,您可以尝试pg_tgrm
索引。