SQL SELECT语句在执行过程中实际做什么?

SQL SELECT语句在执行过程中实际做什么?,sql,database,Sql,Database,在语句中选择: SELECT name FROM users WHERE address IN (addr_a, addr_b, addr_c, ...); 我们知道,它将选择地址在(地址a、地址b、地址c,…)中的所有人的姓名。但我想知道它在执行这个语句时实际做了什么 例如,它是否搜索表中的每个元素以检查其地址是否在(addr_a,…)中 如果addr\u a,addr\u b太长,是否会减慢搜索过程 关于这些东西有什么值得推荐的材料吗 编辑:我没有指定RDBMS,因为我想知道尽可能多的

语句中选择

SELECT name 
FROM users 
WHERE address IN (addr_a, addr_b, addr_c, ...);
我们知道,它将选择地址在(地址a、地址b、地址c,…)中的所有人的姓名。但我想知道它在执行这个语句时实际做了什么

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

如果
addr\u a
addr\u b
太长,是否会减慢搜索过程

关于这些东西有什么值得推荐的材料吗

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

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

详细解释了它的功能

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

因此,在MySQL对参数进行排序以进行比较时,参数的顺序实际上并不重要。

正确地解释了它的作用

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


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

因为您还没有指定您的问题是关于哪些RDBMS的,所以我将写下它在SQL Server上的工作原理,尝试将其简化一点并避免许多技术细节。在不同的系统上可能相同或非常相似,但也可能完全不同

SQL Server将如何处理您的查询

`SELECT name FROM users WHERE address IN (addr_a, addr_b, addr_c, ...);`
这几乎完全取决于表上有什么类型的索引。以下是3种基本场景:

情景1(良好指数)

如果您有所谓的,这意味着列
address
上的主键或聚集索引,或
address
上的非聚集索引,其中包括
名称
,SQL Server将执行称为
索引查找
的操作。这意味着它将遍历索引的树结构,并快速确定您需要的确切行(或发现它不存在)。因为
name
列也包含在索引中,所以它将读取它并从那里返回

场景2(指数不太好)

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

场景3(无可用索引)

如果您根本没有索引或列地址上没有索引,就会发生这种情况。简单地说,SQL Server会检查所有行,并检查每一行的情况。这称为
索引扫描
(如果根本没有索引,则称为
表格扫描
)。通常是最糟糕的 案例场景,而且是最慢的

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


至于另一个关于长串减速的子问题,这个问题的答案是“可能不会太多”。当SQLServer比较两个字符串时,会逐个字符进行比较,因此如果两个字符串的首字母不同,则不会进一步检查。但是,如果在字符串的开头加上一个通配符%,即:
像“%addr\u a”这样的地址,SQL Server将必须检查列中每个字符串的每个字符,因此工作速度要慢得多。

由于您没有指定您的问题是关于哪些RDBMS,我将写下它在SQL Server上的工作原理,尽量简化一点,避免很多技术问题。在不同的系统上可能相同或非常相似,但也可能完全不同

SQL Server将如何处理您的查询

`SELECT name FROM users WHERE address IN (addr_a, addr_b, addr_c, ...);`
这几乎完全取决于表上有什么类型的索引。以下是3种基本场景:

情景1(良好指数)

如果您有所谓的,这意味着列
address
上的主键或聚集索引,或
address
上的非聚集索引,其中包括
名称
,SQL Server将执行称为
索引查找
的操作。这意味着它将遍历索引的树结构,并快速确定您需要的确切行(或发现它不存在)。因为
name
列也包含在索引中,所以它将读取它并从那里返回

场景2(指数不太好)

当您在列
地址
上有索引时就是这种情况,该列不包括列
名称
。您可能会经常在一列上找到此类索引,但您很快就会发现,它们在大多数情况下都是毫无用处的。您希望SQL Server遍历您的索引结构(seek)并快速找到包含您地址的行。但是,由于列
name
现在不存在,它只能获取行实际所在的rowID(或PK),因此它将为返回的每一行额外读取另一个索引或表,以查找您的行并检索名称。因为这需要3倍于场景1的阅读量