不同的索引用于具有不同 companyid 的相同查询

Different Indexes are used for same query with different companyid's

我们在我们的 RDS 实例上 运行 以下查询,它花费了大量时间,并且对于不同的 companyId 它在一秒钟内执行。

查询:

select *
from items_1_primary
WHERE items_1_primary.item_type_id IN (1,2)
  AND items_1_primary.hidden IS NULL
  AND items_1_primary.company_id = 9130347227057236
ORDER BY items_1_primary.id
LIMIT 1 OFFSET 0;

仅供参考这是两个不同公司的查询计划

inventorymigrationprod=> explain analyze select * from items_1_primary WHERE items_1_primary.item_type_id IN (1,2) AND items_1_primary.hidden IS NULL AND items_1_primary.company_id =9130347227057236 ORDER BY items_1_primary.id LIMIT 1 OFFSET 0;

QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=0.57..1894.58 rows=1 width=332) (actual time=372100.718..372100.719 rows=1 loops=1)
  -> Index Scan using items_1_primary_pkey on items_1_primary (cost=0.57..175867668.27 rows=92855 width=332) (actual time=372100.717..372100.717 rows=1 loops=1)
     Filter: ((hidden IS NULL) AND (item_type_id = ANY ('{1,2}'::numeric[])) AND (company_id = '9130347227057236'::numeric))
     Rows Removed by Filter: 535927031
Planning Time: 1.626 ms
Execution Time: 372100.745 ms
(6 rows)
inventorymigrationprod=> explain analyze select * from items_1_primary WHERE items_1_primary.item_type_id IN (1,2) AND items_1_primary.hidden IS NULL AND items_1_primary.company_id =9130348260181756 ORDER BY items_1_primary.id LIMIT 1 OFFSET 0;
                                          QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=10659.77..10659.77 rows=1 width=332) (actual time=9.559..9.560 rows=1 loops=1)
  -> Sort (cost=10659.77..10665.38 rows=2242 width=332) (actual time=9.557..9.558 rows=1 loops=1)
     Sort Key: id
     Sort Method: top-N heapsort Memory: 25kB
     -> Index Scan using items_1_primary_company_id_item_type_id on items_1_primary (cost=0.57..10648.56 rows=2242 width=332) (actual time=0.057..6.117 rows=10823 loops=1)
        Index Cond: ((company_id = '9130348260181756'::numeric) AND (item_type_id = ANY ('{1,2}'::numeric[])))
        Filter: (hidden IS NULL)
Planning Time: 0.138 ms
Execution Time: 9.589 ms
(9 rows)

数据库实例:inventory-migration-prod-cluster

Indexes On Table
--------------------------
indexes:
“items_1_primary_pkey” PRIMARY KEY, btree (id)
 “items_1_primary_company_id_item_type_id” btree (company_id, item_type_id)
 “items_1_primary_uniqueness” UNIQUE CONSTRAINT, btree (company_id, item_id)

要么 PostgreSQL 高估了满足条件的行数,要么它们在 table.

中以不利的方式分布

如果是第一种情况,加ANALYZE(也许加上default_statistics_target)就可以解决问题。

但是无论是什么原因导致的问题,您都可以通过更改 ORDER BY 子句使 PostgreSQL 无法使用索引来避免它:

ORDER BY items_1_primary.id + 0