需要帮助提高 SQL DELETE 性能
Posted
技术标签:
【中文标题】需要帮助提高 SQL DELETE 性能【英文标题】:Need help improving SQL DELETE performance 【发布时间】:2020-09-26 03:55:59 【问题描述】:我有两个关系,客户和地址。首先,我没有修改数据库的权限(比如为客户和地址创建新的信息)。 我需要的是,给定一个州列表,删除具有与该州相关的 Adress1 或 Adress2 的客户。 我在下面做的很慢,所以任何帮助都将不胜感激。
foreach (State state in listOfStates)
query =
"DELETE FROM CUSTOMER
WHERE EXISTS (
SELECT * FROM ADRESS
WHERE CUSTOMER.ADRESS1 = ADRESS.ID
AND STATE = " + state + ")";
cmd.CommandText = query;
cmd.ExecuteNonQuery();
query =
"DELETE FROM CUSTOMER
WHERE EXISTS (
SELECT * FROM ADRESS
WHERE CUSTOMER.ADRESS2 = ADRESS.ID
AND STATE = " + state + ")";
cmd.CommandText = query;
cmd.ExecuteNonQuery();
Customer
+----------+---------+---------+--+
| Name | Adress1 | Adress2 | |
+----------+---------+---------+--+
| John Doe | 1 | 2 | |
| Victor | 3 | 4 | |
| Renat | 5 | 6 | |
+----------+---------+---------+--+
Adress
+----+--------+------+------------+
| ID | Street | City | State |
+----+--------+------+------------+
| 1 | xxx | xxx | California |
| 2 | xxx | xxx | Florida |
| 3 | xxx | xxx | California |
| 4 | xxx | xxx | Ohio |
| 5 | xxx | xxx | Virginia |
| 6 | xxx | xxx | Colorado |
+----+--------+------+------------+
【问题讨论】:
我正在使用 c# 和 Access SQL 命令真的正确吗?实际上,他们执行如下操作:“如果存在某些记录,则从表customer
中删除所有记录”。也就是说,这些查询总是删除所有客户。如果这确实是您想要做的,那么最快的方法是删除并重新创建表。
第一个查询删除 Adress1 与当前状态相关的客户。第二个做同样的事情,但使用 Adress2 。
@krokodilko:你错了。子查询与删除语句相关。它只检查客户的地址。因此,只有地址处于查找状态的客户才会被删除。
@krokodilko 不是,DELETE FROM table1 WHERE (some condition involving table1)
只会删除相关行。在这种情况下,过滤器确实涉及customer
表,因此,只会删除相关行。
【参考方案1】:
我建议您为各州建立一个 IN 子句。如果您的 listOfStates 是 List<string>
,则为:
string states = "'" + string.Join("','", listOfStates) + "'";
(这会产生类似'Arizona','Kentucky','Tennessee'
的结果,即一个逗号分隔的字符串,所有状态都用单引号括起来。)
如果 listOfStates 不是List<string>
,则调整以上内容以满足您的集合类型,例如
string states = "'" + string.Join("','", listOfStates.Select(state => state.Name)) + "'";
然后为所有状态运行一个删除语句:
query =
"DELETE FROM customer
WHERE EXISTS (
SELECT * FROM adress
WHERE adress.id IN (customer.adress1, customer.adress2)
AND adress.state IN (" + states + "))";
cmd.CommandText = query;
cmd.ExecuteNonQuery();
【讨论】:
我喜欢这种方法。尽管 DELETE 查询仍然很慢,但平均时间呈指数级增长,因为它只评估了一次。【参考方案2】:根据我的 Access 经验,联接通常比 WHERE EXISTS 子句快得多。
这应该可以通过复合 JOIN 实现。以下是空气代码,但应该可以工作。
Access 喜欢在非平凡的 JOIN 子句中使用很多括号。
SELECT c.*
FROM CUSTOMER c
INNER JOIN ADRESS a
ON ((c.ADRESS1 = a.ID OR c.ADRESS2 = a.ID)
AND (a.STATE = <state>)
)
如果上述方法有效,只需将 SELECT 替换为 DELETE。
您也可以将此与 Thorsten 的建议结合起来:
AND (a.STATE IN ('state1', 'state2'))
【讨论】:
。 .根据我的经验(主要在其他数据库上),join
s 并不比exists
“通常快得多”。您在 MS Access 上对此有参考吗?
不,只是个人使用 Access 数据库引擎的经验。我想我应该更具体一些。
。 .您是否对此进行了特定的计时,尤其是使用适当的索引?以上是关于需要帮助提高 SQL DELETE 性能的主要内容,如果未能解决你的问题,请参考以下文章