加快查询,其中不满足其中一个条件

时间:2017-08-25 14:25:12

标签: postgresql

我在一个大表上有一个简单的查询:

UPDATE a
SET a.xyz = b.xyz   
FROM b  
WHERE a.xyz IS NULL AND b.id=a.id

现在所有的a.xyz都不是NULL。但是查询执行的时间几乎与所有a.xyz为NULL时一样长(5分钟)。

以下内容在不到一秒的时间内执行

UPDATE a
SET a.xyz = 1   
WHERE a.xyz IS NULL 

所以,我想知道当大多数a.xyz不是NULL时是否有办法加速第一个查询

P.S。澄清:是的,a.xyz,b.xyz,a.id,b.id上的索引存在

P.S.2。在(a.xyz,a.id)上添加复合索引并在a.xyz WHERE a.xyz IS NULL上添加索引后,时间下降到83秒。但是必须有一种方法可以将其降低到不到一秒,因为没有要更新的记录,并且SELECT COUNT(*)FROM WHERE a.xyz IS NULL在不到一秒的时间内执行

P.S.3。解决了。问题在于另一个触发器无意中触发更新。 (a.xyz,a.id)上的复合索引和a.xyz上的附加索引WHERE a.xyz IS NULL似乎解决了剩余的速度问题

2 个答案:

答案 0 :(得分:1)

确保您拥有a.idb.id

的索引

使用EXPLAIN运行查询以查看数据库引擎使用的计划。如果说Index Scan你没有索引,你应该寻找Seq Scan的内容。

EXPLAIN ANALYZE 
UPDATE a
SET a.xyz = b.xyz   
FROM b  
WHERE a.xyz IS NULL AND b.id=a.id

此外,如果您使用(a.id, a.xyz)创建复合索引,则可以获得更好的性能

以下是一个例子:

EXPLAIN ANALYZE
SELECT *
FROM projects
JOIN images
using (project_id)
WHERE project_id =1

你可以看到project_pk有项目索引,但没有图像索引。

"Nested Loop  (cost=0.15..17.31 rows=273 width=92) (actual time=0.029..0.110 rows=320 loops=1)"
"  ->  Index Scan using project_pk on projects  (cost=0.15..8.17 rows=1 width=52) (actual time=0.012..0.013 rows=1 loops=1)"
"        Index Cond: (project_id = 1)"
"  ->  Seq Scan on images  (cost=0.00..6.41 rows=273 width=44) (actual time=0.007..0.049 rows=320 loops=1)"
"        Filter: (project_id = 1)"
"Planning time: 0.172 ms"
"Execution time: 0.161 ms"

答案 1 :(得分:1)

a.xyz上创建部分索引:

create index a_xyz_null on a (xyz)
where xyz is null

https://www.postgresql.org/docs/9.6/static/indexes-partial.html