详细聊聊MySQL中的LIMIT语句


鏈杩戞湁澶氫釜灏忎紮浼村湪绛旂枒缇ら噷闂簡灏忓瀛愬叧浜嶭IMIT鐨勪竴涓棶棰橈紝涓嬭竟鎴戞潵澶ц嚧鎻忚堪涓涓嬭繖涓棶棰樸?/p>

闂

涓轰簡鏁呬簨鐨勯『鍒╁彂灞曪紝鎴戜滑寰楀厛鏈変釜琛細

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;

琛╰鍖呭惈3涓垪锛宨d鍒楁槸涓婚敭锛宬ey1鍒楁槸浜岀骇绱㈠紩鍒椼傝〃涓寘鍚?涓囨潯璁板綍銆?/p>

褰撴垜浠墽琛屼笅杈硅繖涓鍙ョ殑鏃跺欙紝鏄娇鐢ㄤ簩绾х储寮昳dx_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)

杩欎釜寰堝ソ鐞嗚В锛屽洜涓哄湪浜岀骇绱㈠紩idx_key1涓紝key1鍒楁槸鏈夊簭鐨勩傝屾煡璇㈡槸瑕佸彇鎸夌収key1鍒楁帓搴忕殑绗?鏉¤褰曪紝閭ySQL鍙渶瑕佷粠idx_key1涓幏鍙栧埌绗竴鏉′簩绾х储寮曡褰曪紝鐒跺悗鐩存帴鍥炶〃鍙栧緱瀹屾暣鐨勮褰曞嵆鍙?/p>

浣嗘槸濡傛灉鎴戜滑鎶婁笂杈硅鍙ョ殑LIMIT 1鎹㈡垚LIMIT 5000, 1锛屽垯鍗撮渶瑕佽繘琛屽叏琛ㄦ壂鎻忥紝骞惰繘琛宖ilesort锛屾墽琛岃鍒掑涓嬶細

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)

鏈夌殑鍚屽灏卞緢涓嶇悊瑙d簡锛歀IMIT 5000, 1涔熷彲浠ヤ娇鐢ㄤ簩绾х储寮昳dx_key1鍛锛屾垜浠彲浠ュ厛鎵弿鍒扮5001鏉′簩绾х储寮曡褰曪紝瀵圭5001鏉′簩绾х储寮曡褰曡繘琛屽洖琛ㄦ搷浣滀笉灏卞ソ浜嗕箞锛岃繖鏍风殑浠d环鑲畾姣斿叏琛ㄦ壂鎻?filesort寮哄憖銆?/p>

寰堥仐鎲剧殑鍛婅瘔鍚勪綅锛岀敱浜嶮ySQL瀹炵幇涓婄殑缂洪櫡锛屼笉浼氬嚭鐜颁笂杩扮殑鐞嗘兂鎯呭喌锛屽畠鍙細绗ㄧ鐨勫幓鎵ц鍏ㄨ〃鎵弿+filesort锛屼笅杈规垜浠敔鍙ㄤ竴涓嬪埌搴曟槸鍜嬪洖浜嬪効銆?/p>

server灞傚拰瀛樺偍寮曟搸灞?br />

澶у閮界煡閬擄紝MySQL鍐呴儴鍏跺疄鏄垎涓簊erver灞傚拰瀛樺偍寮曟搸灞傜殑锛?/p>

  • server灞傝礋璐e鐞嗕竴浜涢氱敤鐨勪簨鎯咃紝璇稿杩炴帴绠$悊銆丼QL璇硶瑙f瀽銆佸垎鏋愭墽琛岃鍒掍箣绫荤殑涓滆タ
  • 瀛樺偍寮曟搸灞傝礋璐e叿浣撶殑鏁版嵁瀛樺偍锛岃濡傛暟鎹槸瀛樺偍鍒版枃浠朵笂杩樻槸鍐呭瓨閲岋紝鍏蜂綋鐨勫瓨鍌ㄦ牸寮忔槸浠涔堟牱鐨勪箣绫荤殑銆傛垜浠幇鍦ㄥ熀鏈兘浣跨敤InnoDB瀛樺偍寮曟搸锛屽叾浠栧瓨鍌ㄥ紩鎿庝娇鐢ㄧ殑闈炲父灏戜簡锛屾墍浠ユ垜浠篃灏变笉娑夊強鍏朵粬瀛樺偍寮曟搸浜嗐?/li>

MySQL涓竴鏉QL璇彞鐨勬墽琛屾槸閫氳繃server灞傚拰瀛樺偍寮曟搸灞傜殑澶氭浜や簰鎵嶈兘寰楀埌鏈缁堢粨鏋滅殑銆傛瘮鏂硅涓嬭竟杩欎釜鏌ヨ锛?/p>

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

server灞備細鍒嗘瀽鍒颁笂杩拌鍙ュ彲浠ヤ娇鐢ㄤ笅杈逛袱绉嶆柟妗堟墽琛岋細

  • 鏂规涓锛氫娇鐢ㄥ叏琛ㄦ壂鎻?/li>
  • 鏂规浜岋細浣跨敤浜岀骇绱㈠紩idx_key1锛屾鏃堕渶瑕佹壂鎻弅ey1鍒楀煎湪('a', 'b')涔嬮棿鐨勫叏閮ㄤ簩绾х储寮曡褰曪紝骞朵笖姣忔潯浜岀骇绱㈠紩璁板綍閮介渶瑕佽繘琛屽洖琛ㄦ搷浣溿?/li>

server灞備細鍒嗘瀽涓婅堪涓や釜鏂规鍝釜鎴愭湰鏇翠綆锛岀劧鍚庨夊彇鎴愭湰鏇翠綆鐨勯偅涓柟妗堜綔涓烘墽琛岃鍒掋傜劧鍚庡氨璋冪敤瀛樺偍寮曟搸鎻愪緵鐨勬帴鍙f潵鐪熸鐨勬墽琛屾煡璇簡銆?/p>

杩欓噷鍋囪閲囩敤鏂规浜岋紝涔熷氨鏄娇鐢ㄤ簩绾х储寮昳dx_key1鎵ц涓婅堪鏌ヨ銆傞偅涔坰erver灞傚拰瀛樺偍寮曟搸灞傜殑瀵硅瘽鍙互濡備笅鎵绀猴細

server灞傦細鈥渉ey锛岄夯鐑﹀幓鏌ユ煡idx_key1浜岀骇绱㈠紩鐨?'a', 'b')鍖洪棿鐨勭涓鏉¤褰曪紝鐒跺悗鎶婂洖琛ㄥ悗鎶婂畬鏁寸殑璁板綍杩旂粰鎴戝搱鈥?/p>

InnoDB锛氣滄敹鍒帮紝杩欏氨鍘绘煡鈥濓紝鐒跺悗InnoDB灏遍氳繃idx_key1浜岀骇绱㈠紩瀵瑰簲鐨凚+鏍戯紝蹇熷畾浣嶅埌鎵弿鍖洪棿('a', 'b')鐨勭涓鏉′簩绾х储寮曡褰曪紝鐒跺悗杩涜鍥炶〃锛屽緱鍒板畬鏁寸殑鑱氱皣绱㈠紩璁板綍杩斿洖缁檚erver灞傘?/p>

server灞傛敹鍒板畬鏁寸殑鑱氱皣绱㈠紩璁板綍鍚庯紝缁х画鍒ゆ柇common_field!='a'鏉′欢鏄惁鎴愮珛锛屽鏋滀笉鎴愮珛鍒欒垗寮冭璁板綍锛屽惁鍒欏皢璇ヨ褰曞彂閫佸埌瀹㈡埛绔傜劧鍚庡瀛樺偍寮曟搸璇达細鈥滆鎶婁笅涓鏉¤褰曠粰鎴戝搱鈥?/p>

灏忚创澹細

姝ゅ灏嗚褰曞彂閫佺粰瀹㈡埛绔叾瀹炴槸鍙戦佸埌鏈湴鐨勭綉缁滅紦鍐插尯锛岀紦鍐插尯澶у皬鐢眓et_buffer_length鎺у埗锛岄粯璁ゆ槸16KB澶у皬銆傜瓑缂撳啿鍖烘弧浜嗘墠鐪熸鍙戦佺綉缁滃寘鍒板鎴风銆?/p>

InnoDB锛氣滄敹鍒帮紝杩欏氨鍘绘煡鈥濄侷nnoDB鏍规嵁璁板綍鐨刵ext_record灞炴ф壘鍒癷dx_key1鐨?'a', 'b')鍖洪棿鐨勪笅涓鏉′簩绾х储寮曡褰曪紝鐒跺悗杩涜鍥炶〃鎿嶄綔锛屽皢寰楀埌鐨勫畬鏁寸殑鑱氱皣绱㈠紩璁板綍杩斿洖缁檚erver灞傘?/p>

灏忚创澹細
涓嶈鏄仛绨囩储寮曡褰曡繕鏄簩绾х储寮曡褰曪紝閮藉寘鍚竴涓О浣渘ext_record鐨勫睘鎬э紝鍚勪釜璁板綍鏍规嵁next_record杩炴垚浜嗕竴涓摼琛紝骞朵笖閾捐〃涓殑璁板綍鏄寜鐓ч敭鍊兼帓搴忕殑锛堝浜庤仛绨囩储寮曟潵璇达紝閿兼寚鐨勬槸涓婚敭鐨勫硷紝瀵逛簬浜岀骇绱㈠紩璁板綍鏉ヨ锛岄敭鍊兼寚鐨勬槸浜岀骇绱㈠紩鍒楃殑鍊硷級銆?/p>

server灞傛敹鍒板畬鏁寸殑鑱氱皣绱㈠紩璁板綍鍚庯紝缁х画鍒ゆ柇common_field!='a'鏉′欢鏄惁鎴愮珛锛屽鏋滀笉鎴愮珛鍒欒垗寮冭璁板綍锛屽惁鍒欏皢璇ヨ褰曞彂閫佸埌瀹㈡埛绔傜劧鍚庡瀛樺偍寮曟搸璇达細鈥滆鎶婁笅涓鏉¤褰曠粰鎴戝搱鈥?/p>

... 鐒跺悗灏变笉鍋滅殑閲嶅涓婅堪杩囩▼銆?/p>

鐩村埌锛?/p>

涔熷氨鏄洿鍒癐nnoDB鍙戠幇鏍规嵁浜岀骇绱㈠紩璁板綍鐨刵ext_record鑾峰彇鍒扮殑涓嬩竴鏉′簩绾х储寮曡褰曚笉鍦?'a', 'b')鍖洪棿涓紝灏辫窡server灞傝锛氣滃ソ浜嗭紝('a', 'b')鍖洪棿娌℃湁涓嬩竴鏉¤褰曚簡鈥?/p>

server灞傛敹鍒癐nnoDB璇寸殑娌℃湁涓嬩竴鏉¤褰曠殑娑堟伅锛屽氨缁撴潫鏌ヨ銆?/p>

鐜板湪澶у灏辩煡閬撲簡server灞傚拰瀛樺偍寮曟搸灞傜殑鍩烘湰浜や簰杩囩▼浜嗐?/p>

閭IMIT鏄粈涔堥锛?br />

璇村嚭鏉ュぇ瀹跺彲鑳芥湁鐐瑰効鎯婅锛孧ySQL鏄湪server灞傚噯澶囧悜瀹㈡埛绔彂閫佽褰曠殑鏃跺欐墠浼氬幓澶勭悊LIMIT瀛愬彞涓殑鍐呭銆傛嬁涓嬭竟杩欎釜璇彞涓句緥瀛愶細

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

濡傛灉浣跨敤idx_key1鎵ц涓婅堪鏌ヨ锛岄偅涔圡ySQL浼氳繖鏍峰鐞嗭細

  • server灞傚悜InnoDB瑕佺1鏉¤褰曪紝InnoDB浠巌dx_key1涓幏鍙栧埌绗竴鏉′簩绾х储寮曡褰曪紝鐒跺悗杩涜鍥炶〃鎿嶄綔寰楀埌瀹屾暣鐨勮仛绨囩储寮曡褰曪紝鐒跺悗杩斿洖缁檚erver灞傘俿erver灞傚噯澶囧皢鍏跺彂閫佺粰瀹㈡埛绔紝姝ゆ椂鍙戠幇杩樻湁涓狶IMIT 5000, 1鐨勮姹傦紝鎰忓懗鐫绗﹀悎鏉′欢鐨勮褰曚腑鐨勭5001鏉℃墠鍙互鐪熸鍙戦佺粰瀹㈡埛绔紝鎵浠ュ湪杩欓噷鍏堝仛涓粺璁★紝鎴戜滑鍋囪server灞傜淮鎶や簡涓涓О浣渓imit_count鐨勫彉閲忕敤浜庣粺璁″凡缁忚烦杩囦簡澶氬皯鏉¤褰曪紝姝ゆ椂灏卞簲璇ュ皢limit_count璁剧疆涓?銆?/li>
  • server灞傚啀鍚慖nnoDB瑕佷笅涓鏉¤褰曪紝InnoDB鍐嶆牴鎹簩绾х储寮曡褰曠殑next_record灞炴ф壘鍒颁笅涓鏉′簩绾х储寮曡褰曪紝鍐嶆杩涜鍥炶〃寰楀埌瀹屾暣鐨勮仛绨囩储寮曡褰曡繑鍥炵粰server灞傘俿erver灞傚湪灏嗗叾鍙戦佺粰瀹㈡埛绔殑鏃跺欏彂鐜發imit_count鎵嶆槸1锛屾墍浠ュ氨鏀惧純鍙戦佸埌瀹㈡埛绔殑鎿嶄綔锛屽皢limit_count鍔?锛屾鏃秎imit_count鍙樹负浜?銆?/li>
  • ... 閲嶅涓婅堪鎿嶄綔
  • 鐩村埌limit_count绛変簬5000鐨勬椂鍊欙紝server灞傛墠浼氱湡姝g殑灏咺nnoDB杩斿洖鐨勫畬鏁磋仛绨囩储寮曡褰曞彂閫佺粰瀹㈡埛绔?/li>

浠庝笂杩拌繃绋嬩腑鎴戜滑鍙互鐪嬪埌锛岀敱浜嶮ySQL涓槸鍦ㄥ疄闄呭悜瀹㈡埛绔彂閫佽褰曞墠鎵嶄細鍘诲垽鏂璍IMIT瀛愬彞鏄惁绗﹀悎瑕佹眰锛屾墍浠ュ鏋滀娇鐢ㄤ簩绾х储寮曟墽琛屼笂杩版煡璇㈢殑璇濓紝鎰忓懗鐫瑕佽繘琛?001娆″洖琛ㄦ搷浣溿俿erver灞傚湪杩涜鎵ц璁″垝鍒嗘瀽鐨勬椂鍊欎細瑙夊緱鎵ц杩欎箞澶氭鍥炶〃鐨勬垚鏈お澶т簡锛岃繕涓嶅鐩存帴鍏ㄨ〃鎵弿+filesort蹇憿锛屾墍浠ュ氨閫夋嫨浜嗗悗鑰呮墽琛屾煡璇€?/p>

鎬庝箞鍔烇紵

鐢变簬MySQL瀹炵幇LIMIT瀛愬彞鐨勫眬闄愭э紝鍦ㄥ鐞嗚濡侺IMIT 5000, 1杩欐牱鐨勮鍙ユ椂灏辨棤娉曢氳繃浣跨敤浜岀骇绱㈠紩鏉ュ姞蹇煡璇㈤熷害浜嗕箞锛熷叾瀹炰篃涓嶆槸锛屽彧瑕佹妸涓婅堪璇彞鏀瑰啓鎴愶細

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

杩欐牱锛孲ELECT id FROM t ORDER BY key1 LIMIT 5000, 1浣滀负涓涓瓙鏌ヨ鍗曠嫭瀛樺湪锛岀敱浜庤瀛愭煡璇㈢殑鏌ヨ鍒楄〃鍙湁涓涓猧d鍒楋紝MySQL鍙互閫氳繃浠呮壂鎻忎簩绾х储寮昳dx_key1鎵ц璇ュ瓙鏌ヨ锛岀劧鍚庡啀鏍规嵁瀛愭煡璇腑鑾峰緱鍒扮殑涓婚敭鍊煎幓琛╰涓繘琛屾煡鎵俱?/p>

杩欐牱灏辩渷鍘讳簡鍓?000鏉¤褰曠殑鍥炶〃鎿嶄綔锛屼粠鑰屽ぇ澶ф彁鍗囦簡鏌ヨ鏁堢巼锛?/p>

鍚愪釜妲?br />

璁捐MySQL鐨勫ぇ鍙斿暐鏃跺欒兘鏀规敼LIMIT瀛愬彞鐨勮繖绉嶈秴绗ㄧ殑瀹炵幇鍛紵杩樺緱鐢ㄦ埛鎵嬪姩鎯虫楠椾紭鍖栧櫒鐨勬柟妗堟墠鑳芥彁鍗囨煡璇㈡晥鐜噡

鍒版杩欑瘒鍏充簬MySQL涓璍IMIT璇彞鐨勬枃绔犲氨浠嬬粛鍒拌繖浜?鏇村鐩稿叧MySQL鐨凩IMIT璇彞鍐呭璇锋悳绱㈣剼鏈箣瀹朵互鍓嶇殑鏂囩珷鎴栫户缁祻瑙堜笅闈㈢殑鐩稿叧鏂囩珷甯屾湜澶у浠ュ悗澶氬鏀寔鑴氭湰涔嬪锛?/p>