倒车时选择慢10倍

时间:2011-06-16 04:30:23

标签: 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;

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

select * from char_kills
where rid_first <= 110 and rid_last >= 110
order by kills
limit 500;

你怎么能优化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, , , 

select count(*) from char_kills;

146312

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

7207

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, , 

A

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

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

更多排列

慢速:

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

快速:

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

1 个答案:

答案 0 :(得分:1)

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

将您的数据库(存储为您可能知道的文件)描绘成一个大的矩形玉米田,然后站在它前面。如果你想从位于玉米地4个角落的玉米计划中采摘玉米,那么它显然会变慢(因为你必须走得很远)然后从你面前的玉米植物中采摘玉米。

在计算机中(在任何情况下)距离很重要并且它以IO延迟表示(并且'错过'以在某处找到预期信息)。

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

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

c)您的索引定义不当

编辑:为了说清楚,查询几乎一样快地找到所需的记录,因此问题不在索引或其定义中(至少不是最大的,尝试制作多列索引包含所有列仅用于测试)但当查询显示“确定我知道现在一切都在哪里时,让我去显示它”&lt; - 这个获取过程是杀死其中一个的。