我在 postgres 中有一个名为
orders_table
的表,我正在使用两列 order_id
和 customer_id
创建复合索引。
查询1:
-- Create a new index on order_id and customer_id column
CREATE INDEX idx_orders_table_order_id_customer_id ON
orders_table (order_id, customer_id);
当我分析此查询时,postgres 正在对列运行 Seq Scan
customer_id
EXPLAIN ANALYZE
SELECT
*
FROM
orders_table
WHERE
customer_id = 'VINET'
输出:
Seq Scan on orders_table (cost=0.00..24.38 rows=5 width=90) (actual time=0.018..0.159 rows=5 loops=1)
Filter: (customer_id = 'VINET'::bpchar)
Rows Removed by Filter: 825
Planning Time: 1.160 ms
Execution Time: 0.179 ms
查询2:
但是当我颠倒索引中列的顺序时,例如:
CREATE INDEX idx_orders_table_customer_id_order_id ON
orders_table (customer_id, order_id);
并分析查询:
EXPLAIN ANALYZE
SELECT
*
FROM
orders_table
WHERE
customer_id = 'VINET'
Bitmap Heap Scan on orders_table (cost=4.31..15.41 rows=5 width=90) (actual time=0.040..0.042 rows=5 loops=1)
Recheck Cond: (customer_id = 'VINET'::bpchar)
Heap Blocks: exact=2
-> Bitmap Index Scan on idx_orders_table_customer_id_order_id (cost=0.00..4.31 rows=5 width=0) (actual time=0.036..0.036 rows=5 loops=1)
Index Cond: (customer_id = 'VINET'::bpchar)
Planning Time: 1.269 ms
Execution Time: 0.066 ms
这次执行的是位位图索引扫描而不是顺序扫描。据我所知,由于列的基数较低,因此有利于位图索引扫描。但为什么它不在第一个查询中也执行位图索引扫描呢?有人可以帮助我理解这种行为吗?
列的顺序应与常见的查询模式和过滤条件相匹配,以优化性能。
查询1:前导列(order_id)与查询条件(customer_id)不匹配,因此不使用索引,进行Seq Scan。
对于查询2:前导列(customer_id)与查询条件匹配,允许PostgreSQL执行位图索引扫描和位图堆扫描,对于此类查询来说效率更高。