create table if not exists log_role_gold_change(
`id` int(11) primary key auto_increment,
`username` varchar(60) character set utf8 not null,
`roleid` int(11) not null,
`newcount` int(11) not null,
`create_time` int(11) not null
)engine=myisam deafult charset = utf8;
alter table log_role_gold_change add index(`roleid`)
圖SS:從上面的圖形可以看出:
2.當(dāng)執(zhí)行這個(gè)sql時(shí) 要遍歷 所有的行。
1) 如果這個(gè)圖select 只查詢索引字段,order by 索引字段會(huì)用到索引,要不然就是全表排列;(圖SS)
2) 如果有where 條件,比如where roleid=6000256 order by roleid asc . 這樣order by 也會(huì)用到索引!(如果要是這樣的where 條件 就沒有實(shí)際意義了,這里只是做測(cè)試)
注意:
1. 當(dāng)這個(gè)圖的sql 后面 跟上 limit 開始,結(jié)束;時(shí) 一般會(huì)默認(rèn)使用roleid 索引 ,連接類型(type)一般為index .
2.
order by m,n 不要輕易寫這種語(yǔ)句,一般的order by前面的m才是order by的重點(diǎn),后面的n為配角,如果沒有必要,盡量去掉
從上面的圖形可以看出:
第二個(gè)sql 和第三個(gè)個(gè)sql 可以看出
當(dāng)where 條件里的roleid 沒有一個(gè)固定范圍時(shí) 第二個(gè)sql會(huì)出現(xiàn) “using filesort”
所以從第一張圖 和第二張圖可以得出結(jié)論: 當(dāng)order by 的字段在 where 條件中出現(xiàn) 況且 字段有固定值 或者 有固定返回時(shí) 會(huì)用到roleid字段的索引。
有一種情況
我的這張表有2020030 條數(shù)據(jù)
圖S1:
=============================================================
圖S2:
通過 圖S1:
得知roleid 字段唯一的數(shù)據(jù)有 6697 條
create_time 字段唯一的數(shù)據(jù)有 1088425 條
通過圖s2:
可以看出 第一個(gè)sql: 當(dāng)固定好roleid 返回后 通過 roleid 排序(order by ),則會(huì)用到索引(roleid), 查詢數(shù)據(jù)得到了優(yōu)化,說明查詢時(shí) 用索引的排序 去獲取數(shù)據(jù)
第二個(gè)sql 當(dāng)固定 好時(shí)間的返回 (這里的時(shí)間返回為 第一條數(shù)據(jù)插入的時(shí)間,到最后一條數(shù)據(jù)插入的時(shí)間) 最后 這個(gè)sql沒有得到索引的優(yōu)化。
第三個(gè) sql 這一次 把 時(shí)間返回縮小 最后 這個(gè)sql 得到了索引的優(yōu)化了 ,
為什么 第二個(gè)sql 沒有得到優(yōu)化,我的猜測(cè)是 一個(gè)索引節(jié)點(diǎn)如果對(duì)應(yīng)多條數(shù)據(jù),那么 最后這個(gè)索引列生成的索引文件比create_time(一個(gè)節(jié)點(diǎn)對(duì)應(yīng)一條數(shù)據(jù)) 索引列生成的文件較小,還是和查詢的數(shù)量有關(guān)系啊。【沒有驗(yàn)證】,感覺是后者 ,希望有知道的給我講講?
結(jié)論:(引用于http://www.cnblogs.com/zhaoyl/archive/2012/05/04/2483513.html)
當(dāng)order by 字段出現(xiàn)在where條件中時(shí),才會(huì)利用索引而無需排序操作。其他情況,order by不會(huì)出現(xiàn)排序操作。
分析:
為什么只有order by 字段出現(xiàn)在where條件中時(shí),才會(huì)利用該字段的索引而避免排序。這要說到數(shù)據(jù)庫(kù)如何取到我們需要的數(shù)據(jù)了。
一條SQL實(shí)際上可以分為三步。
1.得到數(shù)據(jù)
2.處理數(shù)據(jù)
3.返回處理后的數(shù)據(jù)
$sql=select sid from log_role_gold_change where id > 1000 and id < 2000 order by id desc;
比如上面的這條語(yǔ)句$sql;
第一步:根據(jù)where條件和統(tǒng)計(jì)信息生成執(zhí)行計(jì)劃,得到數(shù)據(jù)。
第二步:將得到的數(shù)據(jù)排序。
當(dāng)執(zhí)行處理數(shù)據(jù)(order by)時(shí),數(shù)據(jù)庫(kù)會(huì)先查看第一步的執(zhí)行計(jì)劃,看order by 的字段是否在執(zhí)行計(jì)劃中利用了索引。如果是,則可以利用索引順序而直接取得已經(jīng)排好序的數(shù)據(jù)。如果不是,則排序操作。
第三步:返回排序后的數(shù)據(jù)。
另外:
上面的2百多萬(wàn)的數(shù)據(jù)sort只用了0.8ms,也許大家覺得sort不怎么占用資源。可是,由于上面的表的數(shù)據(jù)是有序的,所以排序花費(fèi)的時(shí)間較少。如果 是個(gè)比較無序的表,sort時(shí)間就會(huì)增加很多了。另外排序操作一般都是在內(nèi)存里進(jìn)行的,對(duì)于數(shù)據(jù)庫(kù)來說是一種CPU的消耗,由于現(xiàn)在CPU的性能增強(qiáng),對(duì) 于普通的幾十條或上百條記錄排序?qū)ο到y(tǒng)的影響也不會(huì)很大。但是當(dāng)你的記錄集增加到上百萬(wàn)條以上時(shí),你需要注意是否一定要這么做了,大記錄集排序不僅增加了 CPU開銷,而且可能會(huì)由于內(nèi)存不足發(fā)生硬盤排序的現(xiàn)象,當(dāng)發(fā)生硬盤排序時(shí)性能會(huì)急劇下降。
注:ORACLE或者DB2都有一個(gè)空間來供SORT操作使用(上面所說的內(nèi)存排序),如ORACLE中是用戶全局區(qū)(UGA),里面有SORT_AREA_SIZE等參數(shù)的設(shè)置。如果當(dāng)排序的數(shù)據(jù)量大時(shí),就會(huì)出現(xiàn)排序溢出(硬盤排序),這時(shí)的性能就會(huì)降低很多了。
總結(jié):
當(dāng)order by 中的字段出現(xiàn)在where條件中時(shí),才會(huì)利用索引而不排序,更準(zhǔn)確的說,order by 中的字段在執(zhí)行計(jì)劃中利用了索引時(shí),不用排序操作。
這個(gè)結(jié)論不僅對(duì)order by有效,對(duì)其他需要排序的操作也有效。比如group by 、union t等。
聯(lián)系客服