优化 Postgres 查询

Gan*_*row 1 postgresql performance index postgresql-performance

我有从用户到地址表的一对一关系。一位用户可以拥有一个搜索地址和一个经过验证的地址。

我在地址表上有两个索引:

  • 状态字段索引
  • user_id 上的索引

我正在尝试仅为某些用户获取地址,而那些状态不是manual_verification.

这是我的查询:

SELECT users.id 
FROM "users" INNER JOIN addresses 
     ON  addresses.user_id = users.id 
     and addresses.type = 'VerifiedAddress' 
WHERE ("users".deleted_at IS NULL) 
  AND (users.id in (11144,10569,21519,783,15671,21726,17787,11665,
                    19579,12226,1324,9413,5461,20981,12906) 
  and addresses.state != 'manual_verification')
Run Code Online (Sandbox Code Playgroud)

解释上面的查询:http : //explain.depesz.com/s/rTj

需要 37 毫秒。有时更多取决于用户数量。

我认为这是一个很好的查询,但是我们的团队需要对此进行调查,我正在寻找一些优化技巧。我的意思是我做了一个字段选择,user_id(地址)和状态(地址)上有一个索引。

还有什么我可以做/尝试的吗?

更新

我发现这个查询的工作速度要快得多:

 SELECT "addresses"."user_id" 
    FROM "addresses" 
    WHERE "addresses"."type" IN ('VerifiedAddress') 
    AND (user_id in (9681,23824,23760,20098,962,14730,12294,9552,534,
                     553,5837,6768,6583,956,24179) and state != 'manual_verification')
Run Code Online (Sandbox Code Playgroud)

解释这个查询:http : //explain.depesz.com/s/nHrr

Erw*_*ter 6

我正在尝试仅为某些用户获取地址...

IN不能很好地扩展大列表。将性能与unnest()/JOIN

SELECT a.*
FROM   unnest(ARRAY[9681,23824,23760,20098,962,14730,12294,9552,534,
                    553,5837,6768,6583,956,24179]) AS t(user_id)
JOIN   addresses a USING (user_id)
WHERE  a.type  =  'VerifiedAddress'
AND    a.state <> 'manual_verification'
Run Code Online (Sandbox Code Playgroud)

我希望state并且type至少是enum类型。否则,您应该规范化您的数据库设计。有查找表statetype并且只使用一个小的 ID 引用那里的条目。使addresses桌子更小,一切都更快。

假设所有列都NOT NULL缺少信息。

部分索引

如果您仍然需要更快的速度,并且如果有不止几行带有type <> 'VerifiedAddress'or state = 'manual_verification',则部分索引会有所帮助。收益随着您可以从索引中排除的行的百分比而增长。

CREATE INDEX addresses_selection_idx ON addresses (user_id)
WHERE  type  =  'VerifiedAddress'
AND    state <> 'manual_verification';
Run Code Online (Sandbox Code Playgroud)

确保WHERE在查询中使用匹配条件以允许 Postgres 使用此索引。并权衡定制索引的好处与其成本(维护、额外磁盘空间、写入操作的小损失)。