了解LIKE查询中的慢位图堆扫描

时间:2017-02-06 19:47:59

标签: sql postgresql

以下查询在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)

1 个答案:

答案 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_opsLIKE归类,否则C需要

POSIX

如果搜索模式以通配符开头,则没有B树索引可以提供帮助。在这种情况下,您可以尝试pg_tgrm索引。