【问题标题】:SELECT EXISTS vs. LIMIT 1SELECT EXISTS 与 LIMIT 1
【发布时间】:2012-05-15 10:36:52
【问题描述】:

我看到SELECT EXISTS 很常用:

    if db.query("""
        SELECT EXISTS (
            SELECT 1 FROM checkout
            WHERE checkout_id = %s
        )
    """ % checkout_id).getresult()[0][0] == 't':

对比我更喜欢什么:

    if db.query("""
        SELECT 1 FROM checkout
        WHERE checkout_id = %s
        LIMIT 1
    """ % checkout_id).getresult():

首选哪一个,为什么?

附:我正在使用 Python 和 PosgreSQL。

cert=> explain SELECT EXISTS (SELECT 1 FROM checkout WHERE checkout_id = 3);
                                      QUERY PLAN                                      
--------------------------------------------------------------------------------------
 Result  (cost=4.03..4.03 rows=1 width=0)
   InitPlan
     ->  Index Scan using checkout_pkey on checkout  (cost=0.00..4.03 rows=1 width=0)
           Index Cond: (checkout_id = 3)
(4 rows)

cert=> explain SELECT 1 FROM checkout WHERE checkout_id = 3 limit 1;
                                     QUERY PLAN                                     
------------------------------------------------------------------------------------
 Limit  (cost=0.00..4.03 rows=1 width=0)
   ->  Index Scan using checkout_pkey on checkout  (cost=0.00..4.03 rows=1 width=0)
         Index Cond: (checkout_id = 3)
(3 rows)

我的意思是,为什么要从结果中获取一行并检查它的第一列是否为真,如果我可以检查是否有任何行,意思是一样的?

【问题讨论】:

  • 绝对不是 SQL Server。 LIMIT 1 告诉我这可能是 mysql(只是猜测)
  • PostgreSQL 为两个版本生成(几乎)相同的执行计划。所以他们之间应该没有区别
  • 肯定是mysql……我想他用的是php+mysql。
  • exists 运算符可以在返回的第一行停止,因此即使对于 MySQL 的优化器,这两个语句之间也不应该有区别。
  • 对不起,我认为这不相关:我正在使用 Python 和 PosgreSQL

标签: python sql postgresql


【解决方案1】:

在我看来,第二个语句是有问题的,如果条件不满足,它不会返回一行。

【讨论】:

  • 这真是一个真实的说法。
  • 我不知道这是嵌入在什么程序语言中(php?),所以也许 db.query 引发了异常。
  • 是的,这就是想法——您只需检查是否有任何行返回。如果没有返回行——过滤器没有记录。
【解决方案2】:

PostgreSQL 似乎足够聪明,可以将这两个语句一视同仁,正如您在执行计划中可以清楚地看到的那样。

我对一个本地表的测试,该表有 ~150000 行并且根据条件从中选择了 ~100 行,也显示出相同的行为

底线是:使用哪一个并不重要,但您应该意识到其他 DBMS 的行为方式可能不同。

【讨论】:

    【解决方案3】:

    当您使用EXPLAIN 时,您可以看到第一条语句将执行额外的子查询,而第二条则不会。

    这就是为什么我更喜欢使用limit 而不是exists

    例子:

    explain SELECT EXISTS (SELECT 1 FROM checkout WHERE id = 3);
    explain SELECT 1 FROM checkout WHERE id = 3 limit 1;
    

    【讨论】:

    • 这太难了,你总是指定一个 sunquery 到 exists 来检查行的存在。文档本身说Specifies a subquery to test for the existence of rows
    猜你喜欢
    • 1970-01-01
    • 2013-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-02
    相关资源
    最近更新 更多