小编Arn*_*sen的帖子

Postgres 有时对 WHERE a IN (...) ORDER BY b LIMIT N 使用劣等索引

我们有一个包含约 50 亿行的 PostgreSQL 表,它养成了一个讨厌的习惯,即缺少正确的索引并对某些LIMIT操作进行主键扫描。

问题通常出现在一个ORDER BY .. LIMIT ..子句(Django 分页中的常见模式)上,其中LIMIT是索引匹配的结果的一些相对较小的子集。一个极端的例子是这样的:

SELECT * FROM mcqueen_base_imagemeta2 
  WHERE image_id IN ( 123, ... )
  ORDER BY id DESC
  LIMIT 1;
Run Code Online (Sandbox Code Playgroud)

其中该IN子句中的项目约为 20,索引匹配的总行数image_id为 16。

EXPLAIN表明,它错过了image_id指数,而是确实5B行的PK扫描:

限制(成本=0.58..4632.03 行=1 宽度=28)
   -> 在 mcqueen_base_imagemeta2 上使用 mcqueen_base_imagemeta2_pkey 向后扫描索引(成本=0.58..364597074.75 行=78722 宽度=28)
         过滤器:(image_id = ANY ('{123, ...}'::bigint[]))

如果LIMIT增加到2,它会按预期工作:

限制(成本=7585.92..7585.93 行=2 宽度=28)
   -> 排序(成本=7585.92..7782.73 行=78722 宽度=28)
         排序键:id DESC
         -> 在 mcqueen_base_imagemeta2 上使用 …

postgresql performance index-tuning paging postgresql-9.6 query-performance

5
推荐指数
2
解决办法
531
查看次数