我有一个包含300,000行测试数据的表,我正在尝试为这个select语句提供一个合适的索引,但是我相信没有什么能够非常有效地工作,我可能需要调整我的方法。
x和y可以是1到9之间的任何值,p可以是字面上任何高于x * y的值(所以x为4和y或4,等于16,但它可以是高于该值的任何值,会有没有限制.1和1的x可能有1000的ap,或者可能只是1. 9的9和y的另一个x可能是81的ap,可能是100,可能是10000,它没有限制。 )
SELECT `x`,
`y`
FROM `table`
WHERE `x` <= '9'
AND `y` <= '9'
AND `used` = '0'
ORDER BY `p` DESC
LIMIT 1
我创建了一个......
的索引x, y, used, price
...对于x和y的特定值,效果非常好,但是当要求范围时,这显然需要更多的工作。
有人能看到有效的方法吗?
答案 0 :(得分:0)
对于此查询:
SELECT `x`, `y`
FROM `table`
WHERE `x` <= '9' AND `y` <= '9' AND `used` = '0'
ORDER BY `p` DESC
LIMIT 1;
注意:如果任何值是数字,则删除单引号以进行比较。在某些情况下,比较字符串和数字可能会使优化器更难以完成其工作。
这不是很好的指数。最好的是(used, x, y, p)
。查询仍然需要文件排序。一个问题是where
中的不平等。第二个是MySQL没有为索引中的列实现desc
选项。
答案 1 :(得分:0)
有3种可能的指标。但优化器不太可能始终选择最佳。一切都从过滤一个有用的东西used=0
INDEX(used, price) -- This scans from top price down; it wins if
-- a good x&y are found soon
INDEX(used, x) -- This wins if there are few rows with x<9
INDEX(used, y) -- This wins if there are few rows with y<9
如果您简化了查询,则所有投注均已关闭。特别是以下内容:
通过使用&#34;覆盖索引&#34;,您可以获得额外的提升:
INDEX(used, price, x, y)
INDEX(used, x, y, price)
INDEX(used, y, price, x)
也就是说,如果你真的拥有SELECT x,y,z FROM ...
,那么这些不再是&#34;覆盖&#34;,并且(因为体积更大)更糟糕。
添加3个索引并希望Optimizer猜对了。
注意:used
是真/假旗吗?不要将INT
用于标记;它需要4个字节。使用TINYINT
或ENUM
,它们只需1个字节。