在包含来自具体化查询的主键的临时表上创建索引有什么好处吗?
我想删除特定表中的一些数据,以及其他具有外键引用的相关表。为了提高性能,我将初始选择具体化为临时表,然后加入它以进行后续删除。
临时表只包含一列 - 子查询中的主键。在临时表的id列上创建索引是否有任何性能优势?在我的测试中,我看到了大约2%的改进(更多的是由索引创建的开销抵消),但也许我可以测试的数据集不够大。
CREATE TEMPORARY TABLE ids AS (SELECT id FROM tableA WHERE xxx);
DELETE tableB FROM tableB INNER JOIN ids ON tableB.a_id = ids.id;
DELETE tableC FROM tableC INNER JOIN ids ON tableC.a_id = ids.id;
...
DELETE tableA FROM tableA INNER JOIN ids ON tableA.id = ids.id;
由于来自ids临时表的所有行都将用于删除tableB中的行(a_id已编入索引),因此在ids临时表上创建主键/索引是否有任何性能优势?是否有更好,更完全不同的方法来解决这个问题?
答案 0 :(得分:1)
这完全取决于您运行的查询类型。如果您只运行需要读取或返回整个表或整个表的重要子集的查询,那么添加索引只会导致写入性能下降(它总是这样做)。如果您经常执行可以使用这样的索引的查询来减少表中的磁盘页面I / O数量(因为您只查找一行或者很小的行数),那么添加索引将显着提高了这些查询的性能。
答案 1 :(得分:0)
实际上,这是主键索引可能对性能造成危险的一种情况。
您拥有的查询基本上有两个逻辑执行路径。一种是阅读“其他”表并在ID中查找值。第二个是读取id表并在“other”表中查找值。后一个执行计划是最好的,假设id比另一个表小得多。
主键索引的问题在于它可能会使优化器混淆,因为它确实使第一个选项看起来合理。如果您信任优化器,那么拥有索引就没问题了。但它确实增加了混淆的可能性。
现在为了进一步混淆问题,有些情况下索引会非常有益。当ids
表相对于其他表较大时会发生这种情况 - 而且这些表也很大。在这种情况下,您希望以“主键”顺序为“其他”表执行删除操作。因此,按顺序阅读该表并查找id是有道理的。只有当大多数页面上至少有两个要删除的记录时才会出现这种情况。