我想知道下面的MySQL SELECT查询是O(N)还是O(LogN).

让我们有一个表示4个整数区间[startNum,endNum]的表. 该表由startNum和endNum列编制索引.

startNum, endNum
3, 8
10, 15
16, 21
28, 42

-你在说什么?

SELECT * from table
where startNum <= 19 AND endNum >= 19

我认为MySQL将采用O(N),因为它将

 1. find the first 3 rows using the "startNum"; then 
 2. go through each of them and use the "endNum" to identify the 3rd row; then 
 3. return the 3rd row [16, 21] as the result.

MySQL是否足够"聪明"来执行以下操作?

1. binary search on the startNum to find the position of the 3rd row, since "startNum" is sorted; then
2. binary search on the endNum to find the 3rd row again, since "endNum" is also sorted; then
3. return the 3rd row [16, 21] as the result.

来自本文档:https://dev.mysql.com/doc/refman/5.7/en/range-optimization.html

如果运算符是&gt;、&lt;、&gt;=、&lt;=、!=、&lt;&gt;、介于或类似于 优化器使用它,但不考虑更多的关键部件.

我不认为MySQL正在进行"智能"的二进制搜索.

我说的对吗? 有什么配置可以让MySQL执行二进制搜索吗?

推荐答案

你说得对.它是O(N).如果startNum和endNum上都有索引,查询规划器将 Select 一个索引.根据表统计数据,它将try Select 更具 Select 性的索引.

然后,它将随机访问该索引到第一个符合条件的行,并继续扫描表的其余部分,以满足另一个不平等谓词.这是BTREE索引的本质.这种情况在所有使用BTREE索引的表服务器中都是一样的,而不仅仅是MySQL/MariaDB.

如果您的索引是复合索引,如下所示

ALTER TABLE `table`
  ADD INDEX start_end (startNum, endNum),
  ADD INDEX end_start (endNum, startNum);

查询规划者可能会 Select 扫描索引,而不是整个表.这通常更快,但仍然是O(N).

请记住,在性能关键型查询中使用SELECT *是一种反模式,除非您确定需要表中的每一列.

Mysql相关问答推荐

同一类型对象之间的多对多关系

更新MySQL表中子记录的序号

MySQL-如何检测时间戳中的一天

从表中 Select 具有不同顺序的列

GoRM中行最大值查询返回"0"

使用mysql查询获取不关注user1的user3

在 MySQL 中,如何对 LIKE 查询进行批量更新,删除字符?

MySQL - 如何查询涉及前面计算值的表结果

谁能帮我优化低性能的mysql查询

如何 Select 具有最新的 2 个日期字段的行?

MySql部分匹配基于部分查询代码

如何在更新语句中使用多个子字符串函数?

保存SQL查询的中间结果

mysql从另一个表中 Select 不相等的值

使用 MySQL LIMIT、OFFSET 进行分页

mysql错误:错误1018(HY000):无法读取'.'的目录(错误号:13)

Spring Boot:Jdbc javax.net.ssl.SSLException:在接收对等方的 close_notify 之前关闭入站

按 15 分钟间隔对 mysql 查询进行分组

在 MySQL 中签名或未签名

在 MySQL 中仅 Select 仅包含字母数字字符的行