【问题标题】:What does a SQL SELECT statement actually do during execution?SQL SELECT 语句在执行期间实际上做了什么?
【发布时间】:2013-04-02 10:34:11
【问题描述】:

SELECT 声明中:

SELECT name 
FROM users 
WHERE address IN (addr_a, addr_b, addr_c, ...);

我们知道它将选择所有地址在 (addr_a, addr_b, addr_c, ...) 中的人的姓名。但我想知道执行此语句时它实际上做了什么。

例如,它是否搜索表中的每个元素以检查其地址是否在 (addr_a, ...) 中?

如果addr_aaddr_b 太长,是否会减慢搜索速度?

这些东西有什么资料可以推荐吗?

编辑:我没有指定 RDBMS,因为我想知道尽可能多的 SQL 实现。

再次编辑:在这里我得到了关于 MySQL 和 SQL Server 的答案,我接受了“SQL Server”的答案,因为它是一个详细的答案。欢迎更多关于其他 RDBMS 的解答。

【问题讨论】:

  • 你为什么不用'like'?
  • @Praveen 我认为这里的addr_xs 是实际地址的占位符。
  • 这取决于是否在address 上创建索引
  • 什么是 RDBMS? SQL 是一种语言,有许多 SQL 实现。
  • @Praveen:正如@Jared 所说,addr_xs 是实际地址的占位符。

标签: sql database


【解决方案1】:

由于您尚未指定您的问题是哪个 RDBMS,因此我将编写它在 SQL Server 上的工作原理,并尝试对其进行一些简化并避免大量技术细节。在不同的系统上可能相同或非常相似,但也可能完全不同。

SQL Server 将如何处理您的查询

`SELECT name FROM users WHERE address IN (addr_a, addr_b, addr_c, ...);`

几乎完全取决于您在表上拥有什么样的索引。以下是 3 个基本场景:

场景 1(良好的索引)

如果您有所谓的Covering Index,这意味着address 列上的PK 或聚集索引或address 上包括name 的非聚集索引,SQL Server 将执行名为@987654326 的操作@。这意味着它将遍历索引的树结构并快速查明您需要的确切行(或发现它不存在)。由于name 列也包含在索引中,它会读取它并从那里直接返回。

场景 2(不太好的索引)

当您在列 address 上具有索引时会出现这种情况,该列不包括列 name。您可能会经常发现这类索引(仅在一列上),但您很快就会发现它们大部分时间都毫无用处。您在这里希望 SQL Server 通过您的索引结构(搜索)并快速找到您的地址所在的行。但是,由于 name 列现在不存在,它只能获取行实际所在的行 ID(或 PK),因此它将为返回的每一行额外读取另一个索引或表以查找您的行并检索名称。由于这需要比方案 1 多 3 倍的读取,SQL Server 往往不会决定只遍历表的所有行而不是使用索引更便宜。这在场景 3 中进行了解释。

场景 3(无可用索引)

如果您根本没有索引或列地址上没有索引,就会发生这种情况。简单地说,SQL Server 会遍历所有行并检查每一行是否符合您的条件。这称为Index Scan(或Table Scan,如果根本没有索引)。通常是最坏的 案例场景和最慢的。

希望有助于澄清一些事情。

至于关于长字符串减速的另一个子问题 - 这种情况的答案是“可能不多”。当 SQl Server 比较两个字符串时,它会逐个字符地进行比较,因此如果两个字符串的首字母不同,则不会进一步检查。但是,如果您在字符串的开头放置通配符 % 即:WHERE address LIKE '%addr_a' SQL Server 将不得不检查列中每个字符串的每个字符,因此工作速度会慢得多。

【讨论】:

    【解决方案2】:

    documentation 准确解释了它的作用。

    如果所有值都是常量,则根据 expr 的类型对它们进行求值并排序。然后使用二分搜索完成对项目的搜索。

    因此,参数的顺序实际上并不重要,因为 MySQL 无论如何都会对它们进行排序以进行比较。

    【讨论】:

    • 感谢您的回答。有帮助!
    【解决方案3】:

    @Xu :为选择查询创建一个执行计划,并根据该计划完成最终执行。请查看与Execution Plan 相关的基本文档以获取更多详细信息。

    【讨论】:

    • 感谢您的链接!有帮助!
    猜你喜欢
    • 2013-06-21
    • 2013-06-02
    • 2020-11-21
    • 2015-02-26
    • 2017-06-29
    • 2013-06-13
    • 2021-10-25
    • 2011-08-12
    • 1970-01-01
    相关资源
    最近更新 更多