由于您没有指定您的问题是关于哪个 RDBMS,所以我将编写它在 SQL Server 上的工作原理,尝试稍微简化它并避免很多技术性问题。在不同的系统上它可能相同或非常相似,但也可能完全不同。
SQL Server 将如何处理您的查询
`SELECT name FROM users WHERE address IN (addr_a, addr_b, addr_c, ...);`
几乎完全取决于您在表上拥有什么样的索引。这里有3个基本场景:
场景 1(良好的索引)
如果您有所谓的Covering Index,这意味着列上的 PK 或聚集索引或包含address
的非聚集索引,SQL Server 将执行名为. 这意味着它将遍历索引的树结构并快速查明您需要的确切行(或发现它不存在)。由于列也包含在索引中,因此它将读取它并从那里直接返回。address
name
Index Seek
name
场景 2(不太好的索引)
当您在address
不包括 column的 column 上有索引时就是这种情况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 将不得不检查列中每个字符串的每个字符,因此工作速度会慢得多。