mysql order by rand 优化_mysql order by与by rand() 的优化经验
介紹下MySQL中的order by語句。
幾種order by的情況
從最簡單的case開始看起。
用這個表來說明:(10w行數據)
1、? 最簡單的order ―― order by索引字段
從explain的結果來看(Extra列),這個語句并不作排序。因為字段a已經是有順序的。就是按照索引a的順序依次讀pk的值(在這里是隱藏的系統列),一個個從聚簇索引的data中讀入。
2、? 復雜一點 ―― order by 非索引字段
這里Extra列顯示一個Using filesort。這里的filesort并不是指字面上的“文件排序”,說的就是與上面一種情況相比,在Server層作了排序。至于是否使用文件,取決于排序過程中的內存是否足夠,不夠則需要臨時文件。
server層要怎么作排序呢?
一個簡單的想法是把表數據都讀到內存,然后排序。讀到內存當然可以想怎么整就怎么整。但是這個做法很耗費內存。需要占用與表一樣大小的內存。
另外一個做法,只讀入字段b和其對應的主鍵id。可以想象為這兩個字段構成的結構體,按照b的值作排序。排序完成后,按字段b的順序依次取主鍵id,取得結果返回。
實際上第二種作法就是這個例子中的實際執行過程。存放用于排序的字段值的結構我們成為sort_keys.
至于order by b,c這樣的語句,效果與order by b相同,可以簡單理解為上面結構體多了一個字段。
3、? 字段函數排序
還是按順序讀入所有的字段b,只是sort_keys中存的是b的長度而已。
4、? Order by rand()
按照自然想法, order by rand() 也可以仿照上面描述的做法,對于每一行,將生成的rand()的值放入sort_kyes里即可。但實際上上效果如下:
Extra字段里面有一個Using temporary, 也就是說用到了臨時表。那么Using temporary的時候操作流程是怎樣的呢?
a)?????? 創建一個heap引擎的臨時表,字段名為 ”” a b c d, 第一個字段為匿名;
b)?????? 將表tb中的數據按行讀入到臨時表中,同時給第一字段填入一個隨機實數(0,1);
c)?????? 按照第一個字段排序,返回
d)?????? 查詢完成刪除臨時表
分析一下這個過程,由于把數據從InnoDB表里面讀入臨時表,則InnoDB表實際上也已經讀入內存,在這個過程中,若不考慮內存不夠時的寫文件策略, 則內存中有兩份表的全拷貝;另外多了從內存中將數據一一拷貝到臨時表的過程。
這個查詢在測試環境中耗時2.41s(多次次執行,不計第一次加載數據的時間)
order by rand()的改進
實際上對于這種簡單的order by rand() 的情況,也可以等同于按照非索引字段來處理。在sort_array 中存入隨機值即可。
按照這個思路的patch在這里,效果上
說明:執行時間減少為1.89s,性能提升21%, 這個例子單行1k,單行越大提升效果越好。
總結
以上是生活随笔為你收集整理的mysql order by rand 优化_mysql order by与by rand() 的优化经验的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 华为服务器更改从系统盘启动不了,华为服务
- 下一篇: mysql定义条件和处理_mysql s