在PostgreSQL统计中,idx_扫描非常低

在PostgreSQL统计中,idx_扫描非常低,postgresql,optimization,indexing,Postgresql,Optimization,Indexing,我想在PostgresSQL优化方面寻求帮助 我有一个中等大小的表(大约2.000.000条记录),我编写了一个非常简单的查询,如: SELECT COUNT (DISTINCT(user_id)) FROM fp left outer join sd ON fp.session_id = sd.session_id WHERE fp.license_key = 'license' AND sd.device_hash = 'hash' 我对“许可证密钥”、“用户id”和“设备哈希”有简

我想在PostgresSQL优化方面寻求帮助

我有一个中等大小的表(大约2.000.000条记录),我编写了一个非常简单的查询,如:

SELECT COUNT (DISTINCT(user_id)) 
FROM fp left outer join sd ON fp.session_id = sd.session_id 
WHERE fp.license_key = 'license'  AND sd.device_hash = 'hash'
我对“许可证密钥”、“用户id”和“设备哈希”有简单的索引(3个索引) 执行者不想使用我的许可证密钥索引,因为表中有超过700.000个匹配项,Seq Scan是更好的选择

Aggregate  (cost=396247.61..396247.62 rows=1 width=17)

  ->  Hash Join  (cost=99668.54..396152.13 rows=38195 width=17)

        Hash Cond: ((fp.session_id)::text = (sd.session_id)::text)

        ->  Seq Scan on fp  (cost=0.00..293450.55 rows=706957 width=45)

              Filter: ((license_key)::text = 'license'::text)

        ->  Hash  (cost=98678.10..98678.10 rows=79235 width=28)

              ->  Bitmap Heap Scan on sd  (cost=2902.50..98678.10 rows=79235 width=28)

                    Recheck Cond: ((device_hash)::text = 'hash'::text)

                    ->  Bitmap Index Scan on "sd.device_hash_btree_idx"  (cost=0.00..2882.69 rows=79235 width=0)

                          Index Cond: ((device_hash)::text = 'hash'::text)
我检查了我的统计数据:

select * from where indexrelname= 'fp_license_key_btree_idx'

relid   |   indexrelname    |   idx_scan   |   idx_tup_read    |   idx_fetch
----------------------------------------------------------------------------
16430   |fp.license_key_btree_idx | 451    |    13641445       |    13641445

你能给我一些建议吗?如何改进我的idx\U扫描?谢谢

您可以尝试使用CTE和新索引:

CREATE INDEX ON fp USING btree(session_id); --maybe cover license_key as well, but doubt it

WITH s AS (SELECT session_id FROM sd WHERE sd.device_hash = 'hash'),
     f AS (SELECT user_id, session_id
             FROM fp
            WHERE fp.license_key = 'license'
              AND session_id = ANY((SELECT array_agg(session_id) FROM s)::int[]))
SELECT COUNT (DISTINCT(user_id)) 
FROM f
JOIN s ON f.session_id = s.session_id; --your left join is not left join anyway

您可以尝试使用CTE和新索引:

CREATE INDEX ON fp USING btree(session_id); --maybe cover license_key as well, but doubt it

WITH s AS (SELECT session_id FROM sd WHERE sd.device_hash = 'hash'),
     f AS (SELECT user_id, session_id
             FROM fp
            WHERE fp.license_key = 'license'
              AND session_id = ANY((SELECT array_agg(session_id) FROM s)::int[]))
SELECT COUNT (DISTINCT(user_id)) 
FROM f
JOIN s ON f.session_id = s.session_id; --your left join is not left join anyway

谢谢,它快了4倍。我能再问一个问题吗?在cte中,在位图索引扫描之前,查询使用位图堆扫描,它占用了95%的查询时间,我可以避免吗?你不能没有另一个,但你可以使用
set enable\u bitmapscan='off'
禁用该算法,看看它是否会进行正常的索引扫描,并且执行得更好。谢谢,它快了4倍。我能再问一个问题吗?在cte中,在位图索引扫描之前,查询使用位图堆扫描,它占用了它们查询时间的95%,我可以避免吗?你不能没有另一个,但你可以使用
set enable\u bitmapscan='off'
禁用该算法,看看它是否会进行正常索引扫描,并执行更好的操作。