彩虹制造者
发布于

在 Postgres(或任何其他 SQL DB)中建立索引的最佳方法是什么

我有以下查询:

SELECT
    id,
    RANK() OVER (
      PARTITION BY user_id
      ORDER BY
        effective_date <= '${date}' DESC,
        effective_date DESC,
        created_at DESC
    ) AS rank
FROM $table WHERE company_id = $companyId AND effective_date <= $date;

我想在表上添加索引以加快查询的性能。 我的猜测是 (company_id, effective_date) 上有一个综合索引会有所帮助。但是,我还想将 user_id 列添加为索引的一部分。

所以我的问题是:我应该在 (company_id, effective_date, user_id) 上使用单个索引吗?将 userId 作为组合索引的最后一部分是否有助于性能,或者我应该只在 UserID 上添加单独的索引?或者这并不重要,因为它根本无济于事?PARTITION BY user_id

另外值得一提的是:还有一些查询不使用 ranks 和 partition,并且 where 过滤器仅适用于 company_id 和 user_id。在这种情况下,最佳索引选项是 (company_id, user_id)。但是,大多数情况下会使用第一个查询,因此提高该查询的性能将是最重要的目标。

while 在 (company_id, effective_date, user_id) 上具有索引的输出:EXPLAIN (ANALYZE, VERBOSE, BUFFERS, SETTINGS)

WindowAgg  (cost=35.39..36.91 rows=55 width=29) (actual time=0.396..0.596 rows=56 loops=1)
  Output: id, rank() OVER (?), ((effective_date <= '2025-05-30'::date)), effective_date, created_at, user_id
  Buffers: shared hit=5
  ->  Sort  (cost=35.39..35.53 rows=55 width=21) (actual time=0.342..0.352 rows=56 loops=1)
        Output: ((effective_date <= '2025-05-30'::date)), effective_date, created_at, user_id, id
        Sort Key: user_role.user_id, ((user_role.effective_date <= '2025-05-30'::date)) DESC, user_role.effective_date DESC, user_role.created_at DESC
        Sort Method: quicksort  Memory: 29kB
        Buffers: shared hit=5
        ->  Bitmap Heap Scan on public.user_role  (cost=4.84..33.80 rows=55 width=21) (actual time=0.223..0.273 rows=56 loops=1)
              Output: (effective_date <= '2025-05-30'::date), effective_date, created_at, user_id, id
              Recheck Cond: ((user_role.company_id = 47) AND (user_role.effective_date <= '2025-05-30'::date))
              Heap Blocks: exact=3
              Buffers: shared hit=5
              ->  Bitmap Index Scan on user_role__company_id_effective_date_user_id_idx  (cost=0.00..4.83 rows=55 width=0) (actual time=0.170..0.171 rows=56 loops=1)
                    Index Cond: ((user_role.company_id = 47) AND (user_role.effective_date <= '2025-05-30'::date))
                    Buffers: shared hit=2
Settings: jit = 'off'
Planning Time: 0.959 ms
Execution Time: 0.785 ms
浏览 (23)
点赞
收藏
1条评论
Klustron小助手
不会,添加到索引不会加快此特定查询的速度 user_id 由于 与 进行比较,索引扫描的结果不会被 预先排序,因此窗口函数评估无法受益。附加列将使索引更大,因此效率较低,因此除非您可以将第三个索引列用于其他查询,否则请不要添加它 effective_date&lt;user_id
点赞 1
评论