假设我有一个大型网站的数据库,其中有一个名为“用户”的表,其中包含大量记录。当我执行诸如 SELECT * FROM users WHERE username='John'
之类的查询时,我的理解是(忽略缓存等)数据库将导航索引并找到名为 John 的用户。假设此查询返回 100 万个结果,而我只对 John 25 岁的用户感兴趣,因此我执行另一个查询:SELECT * FROM users WHERE username='John' AND age=25
这是如何运作的?它会遍历所有名为 John 的用户并只找到年龄匹配 25 岁的用户,还是有更好的方法?我假设这是特定于数据库和存储引擎的,因此我们可以假设我正在使用 MySQL 和 InnoDB。
最佳答案
答案是——你不应该问这个问题。在像 SQL 这样的声明性语言中,您描述所需的结果,然后处理引擎确定生成结果的最佳方式。根据请求中看似微小的差异,可能会采用不同的路径获得结果,或者使用的方法可能因产品版本而异,甚至基于与产品完全无关的某些因素(可用内存或磁盘空间) ,例如)。
也就是说,在大多数情况下,以下情况适用于大多数 SQL 数据库:
- 数据库将仅使用一个索引来评估 WHERE 子句。
- 如果可以使用多个索引来评估 WHERE 子句,数据库将使用有关每个索引中的基数(值的分布)的统计信息来选择“最佳”索引。
- 如果有一个由多个列构建的索引,并且该索引的 head 列出现在 WHERE 子句的过滤条件中,则该索引可能用于按单个索引中的多列过滤。
因此,在您的示例中,大多数数据库会使用年龄或姓名索引来进行第一级过滤,然后扫描生成的记录以进行第二级过滤。唯一的异常(exception)是,如果您在 (name, age) 或 (age, name) 上有复合索引,在这种情况下,只需要索引扫描即可找到记录。
关于mysql - 'and' 和 'or' 在 SQL 中是如何工作的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27350485/