【发布时间】:2018-05-27 16:02:01
【问题描述】:
我正在使用 MySQL 数据库,并且有下表:
CREATE TABLE SomeTable (
PrimaryKeyCol BIGINT(20) NOT NULL,
A BIGINT(20) NOT NULL,
FirstX INT(11) NOT NULL,
LastX INT(11) NOT NULL,
P INT(11) NOT NULL,
Y INT(11) NOT NULL,
Z INT(11) NOT NULL,
B BIGINT(20) DEFAULT NULL,
PRIMARY KEY (PrimaryKeyCol),
UNIQUE KEY FirstLastXPriority_Index (FirstX,LastX,P)
) ENGINE=InnoDB;
该表包含 430 万行,并且一旦初始化就永远不会更改。
此表的重要列是FirstX、LastX、Y、Z和P。
如您所见,我在行 FirstX、LastX 和 P 上有一个唯一索引。
FirstX 和 LastX 列定义整数范围。
我需要在这个表上运行的查询为给定的 X 获取 FirstX
例如,如果表格包含行(我只包括相关的列):
| FirstX | LastX | P | Y | Z |
|---|---|---|---|---|
| 100000 | 500000 | 1 | 111 | 222 |
| 150000 | 220000 | 2 | 333 | 444 |
| 180000 | 190000 | 3 | 555 | 666 |
| 550000 | 660000 | 4 | 777 | 888 |
| 700000 | 900000 | 5 | 999 | 111 |
| 750000 | 850000 | 6 | 222 | 333 |
例如,我需要包含值185000 的行,应该返回第一行3。
我尝试的查询,应该是使用索引,是:
SELECT P, Y, Z FROM SomeTable WHERE FirstX <= ? AND LastX >= ? LIMIT 10;
即使没有 LIMIT,对于任何给定的 X,此查询也应该返回少量记录(少于 50)。
这个查询是由一个 Java 应用程序针对 X 的 120000 值执行的。令我惊讶的是,它花费了 10 小时 (!),每个查询的平均时间为 0.3 秒。
这是不可接受的,甚至几乎不能接受。它应该更快。
我检查了一个耗时 0.563 秒 的查询,以确保索引正在被使用。我尝试的查询(与上面的查询相同,使用特定整数值而不是 ?)返回 2 行。
我使用EXPLAIN 来了解发生了什么:
id 1
select_type SIMPLE
table SomeTable
type range
possible_keys FirstLastXPriority_Index
key FirstLastXPriority_Index
key_len 4
ref NULL
rows 2104820
Extra Using index condition
如您所见,执行涉及2104820行(接近表的50%的行),即使只有2行满足条件,所以检查了一半的索引以仅返回2行.
查询或索引有问题吗?您能否提出改进查询或索引的建议?
编辑:
一些答案建议我为多个 X 值分批运行查询。我不能这样做,因为我实时运行此查询,因为输入到达我的应用程序。每次输入 X 到达时,我都必须执行 X 的查询并对查询的输出进行一些处理。
【问题讨论】:
-
如果二叉树上的某些点确实被条目堵塞,您可能会在这里遇到非常慢的查询。我知道边界测试在某些类型的数据上的扩展性非常差,这是 3D 类型应用程序中的一个长期存在的问题,例如碰撞检测,因此您可能需要一种比这里的简单索引方法更好的索引方法。
-
@tadman 感谢您的评论。那可能是哪种更好的索引方法?
-
innodb 缓冲池的值是多少?如果服务器专用于仅在 MySQL 上运行,
SELECT @@innodb_buffer_pool_size的总 RAM 应该会减少 75 - 80% -
FirstX 与 P 的组合是唯一的吗? LastX 呢?
-
@Eran,是的,我明白了,但我想知道是否可以定义一对唯一索引,分别省略 FirstX 和 LastX。显然这取决于真实数据。
标签: mysql sql performance