我的USERS表(15M行)包含last_name
(Varchar)和status
(整型)列.姓氏是一些随机姓氏,状态是:
enum status: { active: 0, archived: 1, blocked: 2, inactive: 3, part_active: 4, disabled: 5 }
我想在这上面加上复合指数.我使用的是Rails,所以基本上是这样的:
add_index :users, [:last_name, :status]
我用简单的查询对其进行了测试:
User.where(status: 'active', last_name: 'Anderson').explain(:analyze)
作为计划者的结果,我得到了:
Bitmap Heap Scan on users (cost=4.68..102.86 rows=25 width=108) (actual time=0.559..1.446 rows=489 loops=1)
Recheck Cond: (((last_name)::text = 'Anderson'::text) AND (status = 0))
Heap Blocks: exact=484
-> Bitmap Index Scan on index_users_on_last_name_and_status (cost=0.00..4.68 rows=25 width=0) (actual time=0.091..0.092 rows=489 loops=1)
Index Cond: (((last_name)::text = 'Anderson'::text) AND (status = 0))
Planning Time: 0.133 ms
Execution Time: 1.535 ms
令我惊讶的是,当我更改索引中列的顺序时,我得到了不同的(更简单的)查询计划:
add_index :users, [:status, :last_name]
它的结果是这样一个计划:
Index Scan using index_users_on_status_and_last_name on users (cost=0.43..103.41 rows=25 width=108) (actual time=0.065..0.755 rows=489 loops=1)
Index Cond: ((status = 0) AND ((last_name)::text = 'Anderson'::text))
Planning Time: 0.152 ms
Execution Time: 0.813 ms
我的PostgreSQL版本是13.
为什么我在计划器中因为更改了订单而得到了不同的结果?据我所知,当我只使用相等匹配器时,数据的基数/ Select 性应该不会影响,它应该只影响<;>;等匹配器,就像我判断的示例here一样.