SQL SELECT语句在执行期间实际执行了什么操作?

时间:2013-03-29 05:42:43

标签: sql database

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的更多答案。

3 个答案:

答案 0 :(得分:3)

由于您没有指定哪个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将执行一个名为Index Seek的操作。这意味着它将通过索引的树结构并快速确定您需要的确切行(或找到它不存在)。由于name列也包含在索引中,因此它将读取它并从那里返回。

场景2 (不太好的索引)

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

场景3 (没有可用的索引)

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

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

关于长串减速的其他子问题 - 这个案例的答案可能“可能不多”。当SQl Server比较两个字符串时,它逐个字符,所以如果两个字符串的第一个字母不同,它将不会进一步检查。但是,如果在字符串的开头加上通配符%即:WHERE address LIKE '%addr_a' SQL Server必须检查列中每个字符串的每个字符,因此工作得慢得多。

答案 1 :(得分:2)

documentation确切地解释了它的作用。

  

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

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

答案 2 :(得分:1)

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