Sql 什么是使用where删除或使用where中的子查询删除更快?

Sql 什么是使用where删除或使用where中的子查询删除更快?,sql,postgresql,Sql,Postgresql,我在我的项目中发现了代码的和平 delete from queue where id in( select id from queue where date_part('day', now() - date_of_sending) >= 40) 我认为这种变体更好 delete from queue where date_part('day', now() - date_of_sending) >= 40 当然,服务器会优化这两个查询,但哪一个查询更快?只有数据

我在我的项目中发现了代码的和平

delete from queue where id in(
   select id
   from queue
   where date_part('day', now() - date_of_sending) >= 40)
我认为这种变体更好

delete from queue where date_part('day', now() - date_of_sending) >= 40

当然,服务器会优化这两个查询,但哪一个查询更快?

只有数据库引擎本身可以告诉您哪一个执行得更快(或者执行是否有任何差异)


但是,第一个显然是不必要的复杂,因此第二个是首选的。

在内部查询情况下,如果
内部查询
快,则首先会触发,然后运行主查询。但是,如果只筛选那些包含
where
条件的行,并且只删除那些记录。

警告,对于第一个记录,您将在MySQL中得到一个错误:#1093-您不能在FROM子句中为update指定目标表'queue'。但第二种方法适用于所有地方。

这个问题不仅涉及到查询的速度,还涉及到将子查询合并到原始语句在逻辑上是否正确

首先,您在这里使用的是一个也是唯一一个关系
queue
。因此,发送的
id
date>列属于同一关系。这意味着你的声明:

DELETE FROM queue WHERE date_part('day', now() - date_of_sending) >= 40
是具有子查询的逻辑等价物,您可以使用它

但这不会使您的查询更快

您正在使用列
date\u of\u sending
作为函数调用的一部分。因此,为了DBMS能够使用此构造的索引,您必须在整个表达式上构建一个。为避免此限制并在列上使用可能的索引,请重写(并简化)您的
WHERE
子句,如下所示:

DELETE FROM queue WHERE date_of_sending >= current_date-40;
在研究可能的优化时,最好检查是否有包含列的表达式,并尝试以这样的方式重写这些表达式,即列是以自由形式使用的—这让planner可以更自由地使用索引

是的,正如评论中所建议的,
EXPLAIN(analyze,buffers)
是你的朋友。
请注意,这将实际执行您的
DELETE
语句。因此,您最好将整个内容包装到显式事务中:

BEGIN;
EXPLAIN (analyze, buffers)
  DELETE FROM queue WHERE id IN (
    SELECT id FROM queue
     WHERE date_part('day', now() - date_of_sending) >= 40);
EXPLAIN (analyze, buffers)
  DELETE FROM queue WHERE date_of_sending >= current_date-40;
ABORT;

这个问题似乎离题了,因为它是关于一些可以很容易地为这个特定案例分析和确定的问题,这个案例太本地化了,一开始就无法确定。你自己测试过吗?在许多使用场景中,它可能会改变,即您是否希望删除1行或全部,表中是否有100行或100000000行。但是,如果我被迫猜测,我建议选项2使用
EXPLAIN
自己运行,您将看到的信息将帮助您确定哪个查询更快。注意:只有当
id
字段是主键(或候选键)时,查询才相等。在其他情况下:YMMV.Question被标记为
postgresql
,而不是
mysql
,因此这并不严格适用。