參考原始文檔后, 自已總結一下, 有不對的地方請指正. 在MySQL中進行排序有兩種算法, 以4.1版本為分水嶺, 在此之前排序時的數據只包括ORDER BY中的列和一個記錄的指針(Sort A), 在4.1之后多了一種改進的方法, 排序的數據中可以包括SELECT中的列和ORDER BY中的列(Sort B)
Sort A中最主要的壞處是需要進行二次掃表, 第一次是將ORDER BY的列及記錄指針讀到SORT Buffer中, 然后排序, 如果要排序的數據很多, 不能在內存中完成, 則可能會用到臨時表(tmpdir)空間. 排完序后再根據記錄指針將記錄讀取到READ RND Buffer中, 這一步可能會很慢, 因為這里進行的讀取大都是隨機讀, 而不是順序讀.
Sort B中在第一次掃描表時將SELECT中的列和ORDER BY的列讀到SORT Buffer中, 然后排序, 如果要排序的數據很多, 不能在內存中完成, 則可能會用到臨時表(tmpdir)空間. 排完序后, 就不需要進行二次讀表了, 因為所有的列都已經在第一次中讀出來了. 可以想象, 如果SELECT中的字段很多, 記錄很長, 那么一個Sort Buffer中存放的記錄數就少了, 對於同樣數量的記錄, 就需要進行更多次的排序了, 有可能引起效率的降底.
在MySQL中max_length_for_sort_data變量用於控制何時采用Sort A, 何時采用Sort B, 當SELECT中的列和ORDER BY中的列的長度超過這個設置時采用Sort A, 而在這個以內時采用Sort B. 但依據Oracle上的經驗, 如果這個SQL最后要返回大量記錄, 那么應當選用Sort B, 我們可以在會話級更改設置, 如果返回的記錄很少, 那么可以優先采用Sort A, 因為隨機讀取的成本實在是比較高的.
這些Buffer都會在SQL運行結束時自動釋放. 還有一個問題時, 如果排序中用到了臨時文件, 讀取時是不是受到Read Buffer Size的控制?
是會受到read_buffer_size的控制。
轉自:http://www.anysql.net/mysql/how_mysql_do_sort.html
