2017-08-25 71 views
2

我有一个大表的简单查询的查询:加快,其中条件之一不满足

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

附注:加快第一查询澄清:是的,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 additing指标综合指数似乎已经解决了速度问题的其余

+0

你已经尝试过穿上'a.xyz'的指数? https://dev.mysql.com/doc/refman/5.7/en/mysql-indexes.html – Andy

+0

'a.id'和'b.id'这两个主键(或者至少是:唯一的)? – joop

+0

尝试使用索引,例如“在xyz为空的(id)上创建索引;”哦,我看到Clodoaldo已经提到过。 –

回答

1

请确保您有索引a.idb.id

使用EXPLAIN运行查询以查看数据库引擎使用的计划。如果说Seq Scan你没有索引,你应该寻找Index 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" 
+0

谢谢! \t 谢谢! INDEX ON“a”WHERE a.xyz IS NULL结合组合索引(a.xyz,a.id)将执行时间缩短为83秒。其他建议的指数已经出现。 SELECT COUNT(*)FROM“a”WHERE a.xyz IS NULL仍然小于一秒。因此,逻辑上必须有一种方法将执行时间缩短到不到一秒,因为没有要更新的行。仍然想知道如何。 –

+0

只需用'ANALYZE'返回的当前执行计划更新您的问题,以便我们知道发生了什么。也许连接生成一个更大的表。 –

+0

执行路径只显示索引扫描。成本价值表明执行时间不到一秒钟。 –

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

+0

谢谢! INDEX ON“a”WHERE a.xyz IS NULL结合组合索引(a.xyz,a.id)将执行时间缩短为83秒。但是,SELECT COUNT(*)FROM“a”WHERE a.xyz IS NULL仍然不到一秒。因此,逻辑上必须有一种方法将执行时间缩短到不到一秒,因为没有要更新的行。仍然想知道如何。 –