日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

mysql order by int_mysql order by是怎么工作的?

發布時間:2023/12/1 数据库 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql order by int_mysql order by是怎么工作的? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

假設我們要查詢一個市民表中城市=杭州的所有人的名字,并且按照名字排序

CREATE TABLE `t` (

`id` int(11) NOT NULL,

`city` varchar(16) NOT NULL,

`name` varchar(16) NOT NULL,

`age` int(11) NOT NULL,

`addr` varchar(128) DEFAULT NULL,

PRIMARY KEY (`id`),

KEY `city` (`city`)

) ENGINE=InnoDB;

那么sql語句可以這樣寫

select city,name,age from t where city='杭州' order by name limit 1000 ;

接下來我們看下explain的結果

圖中的Extra這一列下面的Using filesort表示需要排序,MySQL會為每個連接分配一塊內存用于排序,就是sort_buffer,sort_buffer_size可以調整該排序內存大小

因為我們where條件用到了city,所以我們在city上面建立了索引

我們先看下該索引結構

從圖中可以看出滿足city=杭州的條件是ID_X到ID_Y之間的數據

通常情況下這個語句的執行流程如下:

1.初始化sort_buffer,確定放入name,age,city三個字段

2.從索引city中找到第一個符合條件的數據,也就是ID_X這個

3.取出索引中id的值,回表查詢name,age,city的數據放入sort_buffer中

4.從索引city取下一個符合條件的id

5.重復步驟3,4直到city的值不滿足city=杭州的條件,也就是圖中ID_Y

6.對sort_buffer中的數據按照name排序

7.按照排序結果取前1000行數據返回給客戶端

我們把這個排序過程叫全字段排序

如下圖所示

上圖按name排序這個動作可能在內存中完成也可能需要外部排序,這取決于排序需要的內存大小和sort_buffer_size這個參數

如果排序需要的內存大于sort_buffer_size設置的數值,那么就需要使用磁盤臨時文件輔助排序

rowid排序

在上面的那個全字段排序中,只對原表查詢了一次,但是如果查詢的字段很多的話,那么sort_buffer中就會很多數據,就會使用到

磁盤臨時輔助文件排序,這樣性能會變差。

那么如果mysql認為單行數據過大會怎么辦呢?

接下來設置一下這個參數為16

max_length_for_sort_data這個參數是mysql專門用來控制用于排序的行數據的單行的長度的一個參數,如果單行數據的字段的長度超過這個參數設置的值

那么就會使用rowid排序,比如說我們這個例子中name,age,city這三個字段的單行數據長度之和要是大于16,那么就會使用rowid排序

排序流程:

1.初始化sort_buffer,確定放入id,name

2.取出city索引中第一個滿足條件的索引的id值

3.到主鍵id索引里面取出整行,取出name,id字段放入sort_buffer

4.去下一個符合條件的索引記錄,放入sort_buffer中

5.重復步驟3.4直到不滿足city=杭州

6.對sort_buffer中的數據按照name進行排序

7.遍歷排序結果取出前1000行的數據的id,去表中查詢出name,age,city返回給客戶端

可以看出來rowid排序比全字段排序多了一次表查詢就是步驟7

我們來對比下這兩個排序

如果mysql覺得內存不夠用就會用到rowid排序,如果內存夠用則用全字段排序

也就是說Mysql有個設計思想,就是如果內存夠,就盡量用內存,盡量減少磁盤的訪問

看到這里你是不是覺得Mysql排序是一個非常復雜的流程,性能會不好,那么是不是所有的order_by語句都要排序呢?

不是的,如果需要排序的字段天然就是有序的,那么就不需要排序,啥意思呢,比如說我們建立一個city和name的聯合索引

alter table t add index city_user(city, name);

作為與city索引的對比,我們看看這個索引

如果建立了這個索引那么執行流程就變成了這樣

1.查詢出第一條聯合索引中city,name里面city=杭州的數據的id值

2.到主鍵索引里面取出整行,取出name,age,city字段

3.從索引city,name去下一個記錄主鍵id

4.重復步驟2,3直到查到1000條記錄或者不符合city=杭州循環結束

可以看到這個過程不需要排序,也不需要用到臨時表

用explain驗證一下

那么這個語句還有沒有優化空間呢?

有的

我們建立一個三個字段的聯合索引

alter table t add index city_user_age(city, name, age);

那么流程就變成了這樣

1.查詢出索引中第一條符合條件的數據,取出city,name,age作為結果集的一部分直接返回

2.從索引繼續取下一個符合條件的數據作為結果集的一部分直接返回

3.重復步驟2直到查到1000條記錄或者不符合city=杭州循環結束

這里其實就是用到了覆蓋索引,直接不用回表查詢了

當然這里絕對不是說遇到問題就加索引,這里只是舉個例子,因為畢竟維護索引也是有代價的

總結

以上是生活随笔為你收集整理的mysql order by int_mysql order by是怎么工作的?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。