需要帮助提高 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'))

【讨论】:

。 .根据我的经验(主要在其他数据库上),joins 并不比exists“通常快得多”。您在 MS Access 上对此有参考吗? 不,只是个人使用 Access 数据库引擎的经验。我想我应该更具体一些。 。 .您是否对此进行了特定的计时,尤其是使用适当的索引?

以上是关于需要帮助提高 SQL DELETE 性能的主要内容,如果未能解决你的问题,请参考以下文章

需要帮助来提高 MYSQL 子查询性能

需要帮助来提高一些 TSQL“不存在”的查询性能

将值提高到 n 次方时 SQL-Oracle 代码出错 - 需要帮助

提高informix中sql的性能

如何提高风数据SQL查询性能

帮助提高查询的性能