欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

MySQL中的LIMIT語(yǔ)句有什么用

小編給大家分享一下MySQL中的LIMIT語(yǔ)句有什么用,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

成都創(chuàng)新互聯(lián)公司堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:網(wǎng)站制作、做網(wǎng)站、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時(shí)代的拜泉網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!

問(wèn)題

為了故事的順利發(fā)展,我們得先有個(gè)表:

CREATE TABLE t (
    id INT UNSIGNED NOT NULL AUTO_INCREMENT,
    key1 VARCHAR(100),
    common_field VARCHAR(100),
    PRIMARY KEY (id),
    KEY idx_key1 (key1)
) Engine=InnoDB CHARSET=utf8;

表t包含3個(gè)列,id列是主鍵,key1列是二級(jí)索引列。表中包含1萬(wàn)條記錄。

當(dāng)我們執(zhí)行下邊這個(gè)語(yǔ)句的時(shí)候,是使用二級(jí)索引idx_key1的:

mysql>  EXPLAIN SELECT * FROM t ORDER BY key1 LIMIT 1;
+----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-------+
| id | select_type | table | partitions | type  | possible_keys | key      | key_len | ref  | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-------+
|  1 | SIMPLE      | t     | NULL       | index | NULL          | idx_key1 | 303     | NULL |    1 |   100.00 | NULL  |
+----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

這個(gè)很好理解,因?yàn)樵诙?jí)索引idx_key1中,key1列是有序的。而查詢是要取按照key1列排序的第1條記錄,那MySQL只需要從idx_key1中獲取到第一條二級(jí)索引記錄,然后直接回表取得完整的記錄即可。

但是如果我們把上邊語(yǔ)句的LIMIT 1換成LIMIT 5000, 1,則卻需要進(jìn)行全表掃描,并進(jìn)行filesort,執(zhí)行計(jì)劃如下:

mysql>  EXPLAIN SELECT * FROM t ORDER BY key1 LIMIT 5000, 1;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra          |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------+
|  1 | SIMPLE      | t     | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 9966 |   100.00 | Using filesort |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------+
1 row in set, 1 warning (0.00 sec)

有的同學(xué)就很不理解了:LIMIT 5000, 1也可以使用二級(jí)索引idx_key1呀,我們可以先掃描到第5001條二級(jí)索引記錄,對(duì)第5001條二級(jí)索引記錄進(jìn)行回表操作不就好了么,這樣的代價(jià)肯定比全表掃描+filesort強(qiáng)呀。

很遺憾的告訴各位,由于MySQL實(shí)現(xiàn)上的缺陷,不會(huì)出現(xiàn)上述的理想情況,它只會(huì)笨笨的去執(zhí)行全表掃描+filesort,下邊我們嘮叨一下到底是咋回事兒。

server層和存儲(chǔ)引擎層

大家都知道,MySQL內(nèi)部其實(shí)是分為server層和存儲(chǔ)引擎層的:

  • server層負(fù)責(zé)處理一些通用的事情,諸如連接管理、SQL語(yǔ)法解析、分析執(zhí)行計(jì)劃之類的東西

  • 存儲(chǔ)引擎層負(fù)責(zé)具體的數(shù)據(jù)存儲(chǔ),諸如數(shù)據(jù)是存儲(chǔ)到文件上還是內(nèi)存里,具體的存儲(chǔ)格式是什么樣的之類的。我們現(xiàn)在基本都使用InnoDB存儲(chǔ)引擎,其他存儲(chǔ)引擎使用的非常少了,所以我們也就不涉及其他存儲(chǔ)引擎了。

MySQL中一條SQL語(yǔ)句的執(zhí)行是通過(guò)server層和存儲(chǔ)引擎層的多次交互才能得到最終結(jié)果的。比方說(shuō)下邊這個(gè)查詢:

SELECT * FROM t WHERE key1 > 'a' AND key1 < 'b' AND common_field != 'a';

server層會(huì)分析到上述語(yǔ)句可以使用下邊兩種方案執(zhí)行:

  • 方案一:使用全表掃描

  • 方案二:使用二級(jí)索引idx_key1,此時(shí)需要掃描key1列值在('a', 'b')之間的全部二級(jí)索引記錄,并且每條二級(jí)索引記錄都需要進(jìn)行回表操作。

server層會(huì)分析上述兩個(gè)方案哪個(gè)成本更低,然后選取成本更低的那個(gè)方案作為執(zhí)行計(jì)劃。然后就調(diào)用存儲(chǔ)引擎提供的接口來(lái)真正的執(zhí)行查詢了。

這里假設(shè)采用方案二,也就是使用二級(jí)索引idx_key1執(zhí)行上述查詢。那么server層和存儲(chǔ)引擎層的對(duì)話可以如下所示:

MySQL中的LIMIT語(yǔ)句有什么用

server層:“hey,麻煩去查查idx_key1二級(jí)索引的('a', 'b')區(qū)間的第一條記錄,然后把回表后把完整的記錄返給我哈”

InnoDB:“收到,這就去查”,然后InnoDB就通過(guò)idx_key1二級(jí)索引對(duì)應(yīng)的B+樹,快速定位到掃描區(qū)間('a', 'b')的第一條二級(jí)索引記錄,然后進(jìn)行回表,得到完整的聚簇索引記錄返回給server層。

MySQL中的LIMIT語(yǔ)句有什么用

server層收到完整的聚簇索引記錄后,繼續(xù)判斷common_field!='a'條件是否成立,如果不成立則舍棄該記錄,否則將該記錄發(fā)送到客戶端。然后對(duì)存儲(chǔ)引擎說(shuō):“請(qǐng)把下一條記錄給我哈”

小貼士:

此處將記錄發(fā)送給客戶端其實(shí)是發(fā)送到本地的網(wǎng)絡(luò)緩沖區(qū),緩沖區(qū)大小由net_buffer_length控制,默認(rèn)是16KB大小。等緩沖區(qū)滿了才真正發(fā)送網(wǎng)絡(luò)包到客戶端。

InnoDB:“收到,這就去查”。InnoDB根據(jù)記錄的next_record屬性找到idx_key1的('a', 'b')區(qū)間的下一條二級(jí)索引記錄,然后進(jìn)行回表操作,將得到的完整的聚簇索引記錄返回給server層。

小貼士:

不論是聚簇索引記錄還是二級(jí)索引記錄,都包含一個(gè)稱作next_record的屬性,各個(gè)記錄根據(jù)next_record連成了一個(gè)鏈表,并且鏈表中的記錄是按照鍵值排序的(對(duì)于聚簇索引來(lái)說(shuō),鍵值指的是主鍵的值,對(duì)于二級(jí)索引記錄來(lái)說(shuō),鍵值指的是二級(jí)索引列的值)。

MySQL中的LIMIT語(yǔ)句有什么用

server層收到完整的聚簇索引記錄后,繼續(xù)判斷common_field!='a'條件是否成立,如果不成立則舍棄該記錄,否則將該記錄發(fā)送到客戶端。然后對(duì)存儲(chǔ)引擎說(shuō):“請(qǐng)把下一條記錄給我哈”

... 然后就不停的重復(fù)上述過(guò)程。

直到:

MySQL中的LIMIT語(yǔ)句有什么用

也就是直到InnoDB發(fā)現(xiàn)根據(jù)二級(jí)索引記錄的next_record獲取到的下一條二級(jí)索引記錄不在('a', 'b')區(qū)間中,就跟server層說(shuō):“好了,('a', 'b')區(qū)間沒(méi)有下一條記錄了”

server層收到InnoDB說(shuō)的沒(méi)有下一條記錄的消息,就結(jié)束查詢。

現(xiàn)在大家就知道了server層和存儲(chǔ)引擎層的基本交互過(guò)程了。

那LIMIT是什么鬼?

說(shuō)出來(lái)大家可能有點(diǎn)兒驚訝,MySQL是在server層準(zhǔn)備向客戶端發(fā)送記錄的時(shí)候才會(huì)去處理LIMIT子句中的內(nèi)容。拿下邊這個(gè)語(yǔ)句舉例子:

SELECT * FROM t ORDER BY key1 LIMIT 5000, 1;

如果使用idx_key1執(zhí)行上述查詢,那么MySQL會(huì)這樣處理:

  • server層向InnoDB要第1條記錄,InnoDB從idx_key1中獲取到第一條二級(jí)索引記錄,然后進(jìn)行回表操作得到完整的聚簇索引記錄,然后返回給server層。server層準(zhǔn)備將其發(fā)送給客戶端,此時(shí)發(fā)現(xiàn)還有個(gè)LIMIT 5000, 1的要求,意味著符合條件的記錄中的第5001條才可以真正發(fā)送給客戶端,所以在這里先做個(gè)統(tǒng)計(jì),我們假設(shè)server層維護(hù)了一個(gè)稱作limit_count的變量用于統(tǒng)計(jì)已經(jīng)跳過(guò)了多少條記錄,此時(shí)就應(yīng)該將limit_count設(shè)置為1。

  • server層再向InnoDB要下一條記錄,InnoDB再根據(jù)二級(jí)索引記錄的next_record屬性找到下一條二級(jí)索引記錄,再次進(jìn)行回表得到完整的聚簇索引記錄返回給server層。server層在將其發(fā)送給客戶端的時(shí)候發(fā)現(xiàn)limit_count才是1,所以就放棄發(fā)送到客戶端的操作,將limit_count加1,此時(shí)limit_count變?yōu)榱?。

  • ... 重復(fù)上述操作

  • 直到limit_count等于5000的時(shí)候,server層才會(huì)真正的將InnoDB返回的完整聚簇索引記錄發(fā)送給客戶端。

從上述過(guò)程中我們可以看到,由于MySQL中是在實(shí)際向客戶端發(fā)送記錄前才會(huì)去判斷LIMIT子句是否符合要求,所以如果使用二級(jí)索引執(zhí)行上述查詢的話,意味著要進(jìn)行5001次回表操作。server層在進(jìn)行執(zhí)行計(jì)劃分析的時(shí)候會(huì)覺得執(zhí)行這么多次回表的成本太大了,還不如直接全表掃描+filesort快呢,所以就選擇了后者執(zhí)行查詢。

怎么辦?

由于MySQL實(shí)現(xiàn)LIMIT子句的局限性,在處理諸如LIMIT 5000, 1這樣的語(yǔ)句時(shí)就無(wú)法通過(guò)使用二級(jí)索引來(lái)加快查詢速度了么?其實(shí)也不是,只要把上述語(yǔ)句改寫成:

SELECT * FROM t, (SELECT id FROM t ORDER BY key1 LIMIT 5000, 1) AS d
    WHERE t.id = d.id;

這樣,SELECT id FROM t ORDER BY key1 LIMIT 5000, 1作為一個(gè)子查詢單獨(dú)存在,由于該子查詢的查詢列表只有一個(gè)id列,MySQL可以通過(guò)僅掃描二級(jí)索引idx_key1執(zhí)行該子查詢,然后再根據(jù)子查詢中獲得到的主鍵值去表t中進(jìn)行查找。

這樣就省去了前5000條記錄的回表操作,從而大大提升了查詢效率!

以上是“MySQL中的LIMIT語(yǔ)句有什么用”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!

當(dāng)前標(biāo)題:MySQL中的LIMIT語(yǔ)句有什么用
文章鏈接:http://aaarwkj.com/article20/jjppco.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站設(shè)計(jì)、標(biāo)簽優(yōu)化、網(wǎng)站設(shè)計(jì)公司、微信公眾號(hào)面包屑導(dǎo)航

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站建設(shè)
粉嫩av蜜臀一区二区三区| 久久精品国产av一一区| 欧美日韩性视频播放器| 日韩爱爱特级视频中文字幕| 国产三级三级三级精品8ⅰ区| 中文字幕亚洲无级av| 久久91亚洲精品中文字幕| 嫩草网站国产精品一区二| 亚洲中文有码一区二区| 草草视频在线观看网站| 日韩精品一二三黄色一级| 91国内偷拍富婆国内精品对白 | 亚洲激情自拍偷拍视频| 国产极品美女高潮抽搐| 蜜臀人妻久久一区二区三| 精品久久亚洲一区二区欧美| 大香蕉国产精品视频在线| 韩国午夜理伦三级好看| 午夜国产精品福利一二| 尤物在线观看视频播放| 亚洲综合国产一区二区| 放荡精品少妇一区二区三区| 国产模特一区二区三区| 亚洲国产欲色有一二欲色| 给我搜亚洲免费播放黄色大片| 国产精品推荐不卡一区| 欧美系列诱惑性国产精品| 亚洲国产精品日韩专区av有中文| 亚洲第一狼人天堂在线| 麻豆国产自拍在线视频| 日韩欧美亚洲一区二区三区| 日本黄色高清视频一区| 亚洲国产精品综合色在线| 亚洲黄色一区大陆av剧情| 日本欧美自拍偷拍高清| 秋霞三级在线免费观看| 永久免费成人在线视频| 久久久精品免费福利视频| 亚洲一区二区精品欧美日韩| 中文字幕人妻丝袜一区一三区| 亚洲男女尻逼片视频网站|