倒车时选择慢10倍

Qta*_*tax 9 mysql select query-optimization

为什么选择它,称之为A,(0.02406s):

select * from char_kills
where rid_first <= 110 and rid_last >= 110
order by kills desc
limit 500;
Run Code Online (Sandbox Code Playgroud)

比排序顺序慢10倍,称之为B,(0.00229s):

select * from char_kills
where rid_first <= 110 and rid_last >= 110
order by kills
limit 500;
Run Code Online (Sandbox Code Playgroud)

你怎么能优化A?在MySQL 5.5上使用InnoDB表.


更多信息如下.

describe char_kills;

cid, int(10) unsigned, NO, PRI, , 
rid_first, int(10) unsigned, NO, PRI, , 
rid_last, int(10) unsigned, NO, PRI, , 
kills, int(11), NO, PRI, , 
offi_rank, smallint(5) unsigned, YES, , , 
Run Code Online (Sandbox Code Playgroud)

select count(*) from char_kills;

146312
Run Code Online (Sandbox Code Playgroud)

select count(*) from char_kills where rid_first <= 110 and rid_last >= 110;

7207
Run Code Online (Sandbox Code Playgroud)

show indexes from char_kills;

char_kills, 0, PRIMARY, 1, kills, A, 160711, , , , BTREE, , 
char_kills, 0, PRIMARY, 2, rid_first, A, 160711, , , , BTREE, , 
char_kills, 0, PRIMARY, 3, rid_last, A, 160711, , , , BTREE, , 
char_kills, 0, PRIMARY, 4, cid, A, 160711, , , , BTREE, , 
Run Code Online (Sandbox Code Playgroud)

:

Explain:
1, SIMPLE, char_kills, index, , PRIMARY, 16, , 500, Using where

Profiling:
0.02406750, select * from char_kills where rid_first <= 110 and rid_last >= 110 order by kills desc limit 500

starting, 0.000050
checking permissions, 0.000007
Opening tables, 0.000029
System lock, 0.000008
init, 0.000022
optimizing, 0.000008
statistics, 0.000013
preparing, 0.000012
executing, 0.000003
Sorting result, 0.000006
Sending data, 0.023822
end, 0.000007
query end, 0.000004
closing tables, 0.000015
freeing items, 0.000058
logging slow query, 0.000002
cleaning up, 0.000004
Run Code Online (Sandbox Code Playgroud)

B:

Explain:
1, SIMPLE, char_kills, index, , PRIMARY, 16, , 500, Using where

Profiling:
0.00229975, select * from char_kills where rid_first <= 110 and rid_last >= 110 order by kills limit 500

starting, 0.000049
checking permissions, 0.000007
Opening tables, 0.000027
System lock, 0.000008
init, 0.000019
optimizing, 0.000008
statistics, 0.000012
preparing, 0.000009
executing, 0.000003
Sorting result, 0.000004
Sending data, 0.002091
end, 0.000004
query end, 0.000003
closing tables, 0.000010
freeing items, 0.000042
logging slow query, 0.000002
cleaning up, 0.000003
Run Code Online (Sandbox Code Playgroud)

更多的排列

慢:

where rid_first <= 110 and rid_last >= 110 order by kills desc limit 500; -- 0.031s, A, 7k matching rows
where rid_first >= 110 and rid_last <= 110 order by kills      limit 500; -- 0.094s, 449 rows
Run Code Online (Sandbox Code Playgroud)

快速:

where rid_first <= 110 and rid_last >= 110 order by kills      limit 500; -- 0.000s, B
where rid_first <= 110 and rid_last <= 110 order by kills      limit 500; -- 0.000s
where rid_first >= 110 and rid_last >= 110 order by kills desc limit 500; -- 0.000s
where rid_first <= 110 and rid_last <= 110 order by kills desc limit 500; -- 0.000s
where rid_first <= 110 and rid_last <= 110 order by kills desc limit 500; -- 0.000s
where rid_first <= 110                     order by kills desc limit 500; -- 0.000s
where                      rid_last >= 110 order by kills desc limit 500; -- 0.000s
Run Code Online (Sandbox Code Playgroud)

sel*_*ion 1

为什么会发生这种情况的答案相当愚蠢(在问题查询的大量发送数据时间中很明显):

将您的数据库(您可能知道,它存储为文件)想象为一个大的矩形玉米地,而您正站在它前面。如果你想从位于玉米田四个角落的玉米种植区中摘玉米,那么显然比从你面前的玉米种植区中摘玉米要慢(因为你必须走很远)。

在计算机中(在任何事物中),距离很重要,并且它表现为 IO 延迟(并且“错过”在某处找到预期信息)。

所以缓慢的原因是:a)问题查询恰好需要从整个文件读取数据(而不是像快速查询那样顺序读取)

b) 您最近没有对数据库进行碎片整理

c) 你的索引定义不正确

编辑:为了清楚起见,查询找到所需记录的速度几乎一样快,因此问题不在于索引或其定义(至少不是最大的,尝试创建多列索引以包含所有列以进行测试)但是当查询说“好吧,我知道所有东西现在都在哪里,让我去拿它来显示”< - 这个获取过程就是杀死其中一个的原因。