<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
order by 查詢語句使用也是非常頻繁,有時候資料量大了會發現排序查詢很慢,本文就介紹一下 MySQL 是如何進行排序的,以及如何利用其原理來優化 order by 語句。
建立一張表:
CREATE TABLE `cc4` ( `id` INT(11) NOT NULL, `user_name` VARCHAR(16) NOT NULL, `job` VARCHAR(16) NOT NULL, `company` VARCHAR(16) DEFAULT NULL, PRIMARY KEY (`id`), KEY `company_index` (`company`) ) ENGINE=INNODB;
建完表之後,再建立一個指令碼,在指令碼中插入 2000 條資料到前面建好的表cc4 中:
DROP PROCEDURE IF EXISTS cc4_data; DELIMITER ;; CREATE PROCEDURE cc4_data() BEGIN DECLARE i INT; DECLARE company VARCHAR(128); SET i=1; WHILE(i<=2000) DO IF i%6 = 0 THEN SET company= '證券'; ELSEIF i%6 = 1 THEN SET company= '銀行'; ELSEIF i%6 = 2 THEN SET company= '保險'; ELSEIF i%6 = 3 THEN SET company= '科技'; ELSEIF i%6 = 4 THEN SET company= '金融'; ELSE SET company ='傳統'; END IF; INSERT INTO cc4 VALUES(i, CONCAT('孤狼',i), CONCAT('程式設計師',i),company); SET i=i+1; END WHILE; END;; DELIMITER ; CALL cc4_data();
這時候我們如果想要對某一家公司裡面的人按照名字進行排序,一般會這麼寫:
SELECT user_name,job,company FROM cc4 WHERE company='科技' ORDER BY user_name LIMIT 1000;
這是一條非常簡單且常見的 sql 語句,但是就是這麼簡單的一條 sql,它到底是如何被執行的呢?
首先我們對上面的語句執行 explain 語句,看看是怎麼執行的:
explain SELECT user_name,job,company FROM cc4 WHERE company='科技' ORDER BY user_name LIMIT 1000;
可以看到,在最後一列 Extra 中顯示 Using filesort,也就是說用到了檔案排序,這個檔案排序是如何執行的呢?
大概畫出如下一個草圖表示表 cc4 中的索引示意圖:
上圖中顯示 company 欄位為普通索引,再加上主鍵索引,這張表一共有兩個索引,所以這條語句是這麼執行的:
這種排序方式稱之為全欄位排序法。
上面步驟中的第 6 步,排序可以在記憶體中進行,如果記憶體足夠的話,而記憶體是否足夠則取決於 sort_buffer_size 的值,但是我們想一下,如果排序的資料量太大,我們不可能提供足夠的記憶體,那麼這時候就不得不使用磁碟的臨時檔案來進行排序。
那麼我們如何知道當前的排序語句是使用檔案完成排序還是使用記憶體來完成排序呢?
接下來我們執行下面兩句話:
SET optimizer_trace='enabled=on';-- 開啟optimizer_trace,只對本執行緒有效 SELECT user_name,job,company FROM cc4 WHERE company='科技' ORDER BY user_name LIMIT 1000; SELECT * FROM `information_schema`.`OPTIMIZER_TRACE`G -- 檢視 OPTIMIZER_TRACE 輸出
最後這條查詢語句會返回非常多的資訊,包括了具體的查詢步驟,我們看到最後的 filesort_summary:
這裡面有幾個資訊比較關鍵:
接下來我們把預設的排序記憶體改小一點:
SET sort_buffer_size=32768; -- 8.0 版本最小值,無法設定成更小,不同版本之間有差異 show variables like 'sort_buffer_size';
執行之後可以看到排序大小已經被修改為 32k:
接下來我們再來執行排序查詢跟蹤
SELECT user_name,job,company FROM cc4 WHERE company='科技' ORDER BY user_name LIMIT 1000; SELECT * FROM `information_schema`.`OPTIMIZER_TRACE`G -- 檢視 OPTIMIZER_TRACE 輸出
這時候會發現這時候使用到了 6 個臨時檔案進行排序:
在前面的全欄位排序法中其實有些浪費,因為排序只用到了 user_name 欄位,而我們卻同時查詢了其他欄位,這些欄位查詢出來都是會佔用空間的,尤其是當查詢的欄位很多,或者有些欄位又特別長的時候,會佔用很大空間,導致不得不使用檔案排序,而由於欄位多又長,就會造成檔案個數增多,從而導致排序效能會更差。
上面的查詢語句中,我們有沒有辦法不把一些無用的欄位也放到 sort_buffer 中呢?
在 MySQL 中提供了一個欄位 max_length_for_sort_data,預設是 4096
show variables like 'max_length_for_sort_data';
這個欄位是控制用於排序的行資料的長度的一個引數。如果用於排序的單行資料長度超過這個值,MySQL 就認為單行資料太大了,要換一個演演算法,採用 rowid 演演算法。
採用 rowid 演演算法的步驟如下:
這種排序方式對比前面一種全欄位排序,我們發現存的資料更少了,所以需要的記憶體空間更少,但是又有一個更大的問題就是這裡需要進行兩次回表操作,當資料量過大,這也會造成效能影響。
所以我們再結合前面學習的知識,如果排序的時候可以採用覆蓋索引,那麼就不需要進行回表操作,從而大幅度提升效能,這也是覆蓋索引的威力。
首先我們看下面一個例子,執行以下語句:
DROP INDEX company_index ON cc4;-- 刪除索引 CREATE INDEX company_user_index ON cc4 (company,user_name);-- 建立聯合索引 explain SELECT user_name,job,company FROM cc4 WHERE company='科技' ORDER BY user_name LIMIT 1000;
執行結果如下:
可以看到,這次就沒有用到 filesort 了,這是為什麼呢?
因為我們建立了一個聯合索引,而 MySQL 中的 B+ 樹索引是天然有序的,所以當指定了 company,按順序找到的資料,就是按照 user_name 進行的排序,也就不需要再執行一次排序操作了。
到此這篇關於MySQL中如何優化order by語句的文章就介紹到這了,更多相關MySQL優化order by內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45