MySQL 每个查询是否有一个索引的限制?

use*_*951 2 mysql index

MySQL 支持空间索引。然而,空间索引所能做的就是在一个框中找到点。它不能做一些花哨的事情,比如找到最近的 1000 点等。

我想,而且我不知道我哪里出错了,简单地在框中找到点很容易——只需做约束:

x < xmax and x > xmin and y < ymax and y > ymin
Run Code Online (Sandbox Code Playgroud)

是的,这些是使用至少 2 列的 4 个约束。结果是当有 160 万行时,事情变得太慢了。

但为什么?x 和 y 已排序。复杂度应该是log(n)。然而,查询可能需要 60 秒。

使用空间索引通过一些子查询技巧将其缩短到 1 秒。

我错过了什么?为什么在查询中使用一堆约束需要时间?

即使没有花哨的算法,也应该很容易快速获得框中的分数。然而,我觉得O(n)至少应该是复杂的。

Shl*_*ach 6

这里有多个问题。

回答标题:MySQL 可以为每个查询使用多个索引。这称为索引合并

但是,使用索引合并优化并不总是发生。

“正常”索引是 B/B+ 树。这种树提供了线性排序。可以索引x,索引按x升序排序。您可以对y. 您甚至可以对两者进行索引,(x, y)但您仍然可以获得线性排序——而不是二维排序。

回到你的另一个问题,关于查询

x < xmax and x > xmin and y < ymax and y > ymin
Run Code Online (Sandbox Code Playgroud)

让我们假设我们有一个索引 onx和一个索引 on y。问题始于这样一个事实,即这些索引不共享资源,也不共享信息,也不以任何方式相互指向。

x < xmax and x > xmin使用 on 的索引可以很容易地找出所有行 where x。但是一旦你有了这些,你就不能只是将这些行带到y索引并要求它“从我给你的这些行中返回行,并为其 y < ymax 和 y > ymin . The reason is that the index ony can quickly lookup usingy` 值。它不知道如何快速查找行 #3984987。

索引合并的工作方式是从x索引中获取行 id,从索引中获取行 id y(同时x行存储在临时缓冲区中),然后将它们相交。请注意,交集与索引无关。这是一个蛮力操作(希望在线性时间内实现,因为两个行列表已经排序)。

现在给出像你这样的查询,MySQL 会问自己:什么会更便宜?在 上只使用一个索引x,然后逐行过滤那些y < ymax and y > ymin适用的行?或者也许使用索引合并,创建一个临时缓冲区,算出一个蛮力交集?

事实是 MySQL 很少选择索引合并优化。我一直在查看许多查询及其执行计划。非常稀有。也许有人经常这样做。

但是看看 X:Y 坐标问题,很容易看出为什么这行不通:仅 x 范围的匹配值太多,而仅 y 范围的匹配值太多,因此无法作为好计划。