'和'和'or'如何在SQL中工作

问题描述:

想象一下,我有一个大型网站的数据库,该网站有一个名为“users”的表,其中包含大量记录。当我执行查询如SELECT * FROM users WHERE username='John'我的理解是(忽略缓存等)数据库将导航索引并找到名为John的用户。想象一下,这个查询返回100万个结果,我只对25岁的约翰用户感兴趣,所以我执行另一个查询:SELECT * FROM users WHERE username='John' AND age=25'和'和'or'如何在SQL中工作

这是如何工作的?它是否遍历所有名为John的用户,并只查找那些年龄匹配为25的用户,还是有更好的方法来做到这一点?我假设这是数据库和存储引擎的具体情况,所以我们可以假设我在InnoDB中使用MySQL。

+0

从我所了解的情况来看,它会针对每一行都进行比较,而不是针对每个AND/OR条件重新评估...如果您要使用HAVING子句,那将成为另一个故事 – 2014-12-08 02:30:06

+1

您可以使用查询计划器 – 2014-12-08 02:32:20

如果你有这样的查询:

SELECT * 
FROM users 
WHERE username = 'John' AND age = 25; 

则最佳指标是users(username, age)users(age, username)。有了这个索引,匹配记录可以通过在索引中查找来找到。

至于如果你只有username索引会发生什么。它通常会在username列中查找带有“John”的行。然后,它将从数据页获取记录,并继续基于页面上的数据进行过滤。

假设您在两列上都有索引,它通常会检查数据本身的统计信息以选择一个尽可能快地减少结果集基数的选项。

例如,如果20%的人是25,但只有3%年龄在被称为约翰,它会首先得到约翰然后去掉那些谁不老化25

如果你做了一个组合键都是列,那么这应该会更快,因为根本没有“剥离”。底线,它归结为数据库引擎了解数据的组成,并基于此选择最佳执行计划。这就是为什么定期重新计算统计数据通常很好,因为数据可能会发生变化。

答案是 - 你不应该问这个问题。在像SQL这样的声明性语言中,您可以描述所需的结果,并且处理引擎将确定产生结果的最佳方式。根据请求中看似微小的差异可能需要不同的路径才能得出结果,或者所用的方法可能会随产品版本的变化而变化,甚至可能基于某些与产品完全无关的因素(可用内存或磁盘空间, 例如)。

这就是说,以下是 SQL数据库的真正在箱子:

  1. 该数据库将在评估只使用一个索引WHERE子句。
  2. 如果使用多于一个索引可以使用来评估WHERE子句,那么数据库将使用每个索引中基数(值的分布)的统计信息来选择“最佳”子集。
  3. 如果存在由多个列构建的索引,并且该索引的列存在于WHERE子句的过滤条件中,那么该索引可以用于过滤多列一个单一的索引。

因此,在您的示例中,大多数数据库将使用年龄或名称上的索引来执行第一级过滤,然后扫描结果记录以执行第二级过滤。唯一的例外是,如果您在(姓名,年龄)或(年龄,姓名)上有复合索引,在这种情况下只需要进行索引扫描即可查找记录。