我有两张桌子:
table1 (id, name, connte)
table2 (id, name, connte)
它们通过 table1.connte 和 table2.connte 连接。每个都包含100条记录。
现在,如果我想从table1中删除id = 20的记录及其在table2中的相应子项,那么最好是执行以下操作:
DELETE d1,d2 FROM table1 d1 INNER JOIN table2 d2 ON d1.connte= d2.connte WHERE d1.id = 20
或以下:
select connte from table1 where id = 20
--Store connte in a variable say aabc--
delete from table2 where connte = aabc -> execute this first
delete from table1 where id = 20 -> execute this second
如果我想要删除的记录只有一个父项和一个子项(这里是table1.id = 20),那么对整个表进行内连接是不是很昂贵?
我正在从JAVA(所以JDBC)运行此查询,因此对于上述条件,运行多个查询或内部联接是否更加昂贵(性能明智)?
注意:假设表没有参照完整性。所以,我没有使用级联删除。
答案 0 :(得分:6)
在一个查询中执行它可能会更快,而不是两个。您基本上是在尝试自己进行优化,而不是让DBMS这样做,而且通常DBMS'真的很擅长这种东西。
此外,您可能不必担心这么小的表的删除性能。 100 x 100行仍然非常小,因此您的DBMS应该能够毫无问题地处理这个问题。
答案 1 :(得分:3)
执行此操作的最佳方法是对DBMS中的两个查询运行解释计划,输出会为您提供I / O估计等等。一般情况下,只要您对什么更有效率有疑问从DBMS的角度来看,查看查询计划和成本估算是您最好的武器。
SET showplan on
应该在SQL server中工作。这是MSDN documentation,您可能需要稍微不同的语法,具体取决于您的DBMS。 I / O成本估算可能是您最关心的。
对于MySQL,看起来你可以使用
EXPLAIN SELECT * FROM some_table
Here is a tutorial使用Explain分析查询。
总的来说,奥莱克西是正确的;大多数优化器都非常擅长这种事情,并且手动创建临时表并不会对你产生很大影响。很多时候,优化器的查询计划将涉及创建临时表。
对于删除查询,确保速度的一个重要事项是您的delete子句正在使用索引参数,因此不会导致全表扫描。 Explain / Showplan将告诉您查询正在进行什么类型的扫描,以及它正在使用哪些索引。您通常希望避免全表扫描。
答案 2 :(得分:1)
在Sql Server中,您无法从一个删除语句中的两个表中删除(没有触发器或级联删除)。
答案 3 :(得分:0)
为什么不考虑使用外键和级联删除?如果您正确设置了表格,则只需删除父项,然后孩子就会自动得到处理。请参阅此链接When/Why to use Cascading in SQL Server?