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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

MySQL 优化器之Index merge Multi-Range Read MRR与Batched Key Access使用案例详解

發(fā)布時間:2024/9/27 数据库 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MySQL 优化器之Index merge Multi-Range Read MRR与Batched Key Access使用案例详解 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

MySQL 優(yōu)化器之Index merge Multi-Range Read ?MRR與Batched Key Access介紹

索引合并Index merge

覆蓋索引是在索引里即有查詢時需要的字段,而在一個表上的查詢往往條件會有多個組合且較為復(fù)雜,所以很難全部由覆蓋索引包含到。那么此時我們就會用到索引合并(index merge)算法。

該算法主要包含三類情況:

算法

應(yīng)用場景

執(zhí)行計劃

Intersection

and

Using intersect(...)

Union

or

Using or(...)

Sort-Union

帶范圍查詢的or

sort_union(...)

交Intersection算法

EXPLAIN ANALYZE SELECT * FROM sakila.payment WHERE staff_id = 1 AND customer_id = 75; --結(jié)果 -> Filter: ((payment.customer_id = 75) and (payment.staff_id = 1))? (cost=8.12 rows=20) (actual time=2.329..2.637 rows=22 loops=1)-> Index range scan on payment using intersect(idx_fk_customer_id,idx_fk_staff_id)? (cost=8.12 rows=20) (actual time=2.325..2.617 rows=22 loops=1)

從執(zhí)行計劃里我們不難看出這里用到了索引交(intersect)

而通過explain命令則可以看出是

mysql> EXPLAIN SELECT * FROM sakila.payment WHERE staff_id = 1 AND customer_id = 75\G *************************** 1. row ***************************id: 1select_type: SIMPLEtable: paymentpartitions: NULLtype: index_merge possible_keys: idx_fk_staff_id,idx_fk_customer_idkey: idx_fk_customer_id,idx_fk_staff_idkey_len: 2,1ref: NULLrows: 20filtered: 100.00Extra: Using intersect(idx_fk_customer_id,idx_fk_staff_id); Using where

通過觀察該查詢和表的結(jié)構(gòu)可以看出

show create table sakila.payment --結(jié)果 CREATE TABLE `payment` (`payment_id` smallint unsigned NOT NULL AUTO_INCREMENT,`customer_id` smallint unsigned NOT NULL,`staff_id` tinyint unsigned NOT NULL,`rental_id` int DEFAULT NULL,`amount` decimal(5,2) NOT NULL,`payment_date` datetime NOT NULL,`last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,PRIMARY KEY (`payment_id`) USING BTREE,KEY `idx_fk_staff_id` (`staff_id`) USING BTREE,KEY `idx_fk_customer_id` (`customer_id`) USING BTREE,KEY `fk_payment_rental` (`rental_id`) USING BTREE,CONSTRAINT `fk_payment_customer` FOREIGN KEY (`customer_id`) REFERENCES `customer` (`customer_id`) ON DELETE RESTRICT ON UPDATE CASCADE,CONSTRAINT `fk_payment_rental` FOREIGN KEY (`rental_id`) REFERENCES `rental` (`rental_id`) ON DELETE SET NULL ON UPDATE CASCADE,CONSTRAINT `fk_payment_staff` FOREIGN KEY (`staff_id`) REFERENCES `staff` (`staff_id`) ON DELETE RESTRICT ON UPDATE CASCADE ) ENGINE=InnoDB AUTO_INCREMENT=16050 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci

字段staff_id 和customer_id 有各自的索引idx_fk_staff_id、idx_fk_customer_id,而我們的查詢是等值條件的交集。

同理如下查詢也是應(yīng)用到了index merge的intersection算法。

EXPLAIN SELECT * FROM sakila.payment WHERE payment_id > 10 AND customer_id = 318;

并Union算法

當(dāng)一個表查詢中用到一系列的含OR的等值條件時一般會用到并算法。示例查詢見下:

SELECT * FROM sakila.payment WHERE staff_id = 1 OR customer_id = 318;SELECT * FROM sakila.payment WHERE payment_id > 15000 OR customer_id = 318; -- 通過explain或者explain、EXPLAIN ANALYZE() mysql> EXPLAIN SELECT * FROM sakila.payment WHERE staff_id = 1 OR customer_id = 318\G *************************** 1. row ***************************id: 1select_type: SIMPLEtable: paymentpartitions: NULLtype: index_merge possible_keys: idx_fk_staff_id,idx_fk_customer_idkey: idx_fk_staff_id,idx_fk_customer_idkey_len: 1,2ref: NULLrows: 8069filtered: 100.00Extra: Using union(idx_fk_staff_id,idx_fk_customer_id); Using wheremysql> EXPLAIN ANALYZE SELECT * FROM sakila.payment WHERE staff_id = 1 OR customer_id = 318\G *************************** 1. row *************************** EXPLAIN: -> Filter: ((sakila.payment.staff_id = 1) or (sakila.payment.customer_id = 318)) (cost=2306.30 rows=8069) (actual time=0.224..103.595 rows=8062 loops=1) -> Index range scan on payment using union(idx_fk_staff_id,idx_fk_customer_id) (cost=2306.30 rows=8069) (actual time=0.221..98.988 rows=8062 loops=1)mysql> EXPLAIN FORMAT=tree SELECT * FROM sakila.payment WHERE staff_id = 1 OR customer_id = 318\G *************************** 1. row *************************** EXPLAIN: -> Filter: ((sakila.payment.staff_id = 1) or (sakila.payment.customer_id = 318)) (cost=2116.85 rows=8069)-> Index range scan on payment using union(idx_fk_staff_id,idx_fk_customer_id) (cost=2116.85 rows=8069)

排序并Sort Union算法

跟并算法類似,不過這里用的不是等值條件而是范圍,詳見如下例子:

-- 查詢payment表里customer_id小于30或者rental_id小于10的信息。 mysql> EXPLAIN SELECT * FROM sakila.payment WHERE customer_id < 30 OR rental_id < 10\G *************************** 1. row ***************************id: 1select_type: SIMPLEtable: paymentpartitions: NULLtype: index_merge possible_keys: idx_fk_customer_id,fk_payment_rentalkey: idx_fk_customer_id,fk_payment_rentalkey_len: 2,5ref: NULLrows: 826filtered: 100.00Extra: Using sort_union(idx_fk_customer_id,fk_payment_rental); Using where查詢payment表里customer_id小于20或者rental_id大于18000的信息。 mysql> EXPLAIN SELECT * FROM sakila.payment WHERE customer_id < 20 OR rental_id >18000\G *************************** 1. row ***************************id: 1select_type: SIMPLEtable: paymentpartitions: NULLtype: index_merge possible_keys: idx_fk_customer_id,fk_payment_rentalkey: idx_fk_customer_id,fk_payment_rentalkey_len: 2,5ref: NULLrows: 514filtered: 100.00Extra: Using sort_union(idx_fk_customer_id,fk_payment_rental); Using whereEXPLAIN ANALYZE SELECT /*+ NO_INDEX_MERGE(payment) */ * FROM sakila.payment WHERE staff_id = 1 AND customer_id = 75;-> Filter: (payment.staff_id = 1) (cost=12.30 rows=21) (actual time=0.151..0.179 rows=22 loops=1) -> Index lookup on payment using idx_fk_customer_id (customer_id=75) (cost=12.30 rows=41) (actual time=0.149..0.167 rows=41 loops=1) 指定不用index merge的hint。

多范圍讀MRR

多范圍讀MRR概念

多范圍讀即Multi-Range Read (MRR)的主要作用是減少掃描輔助索引時產(chǎn)生的IO隨機讀。優(yōu)化器一般先讀取索引覆蓋的字段,其它字段通過rowid關(guān)聯(lián)到聚集索引而找出。多范圍讀(Multi-Range Read)優(yōu)化可用于使用索引的范圍掃描和等價連接,它不支持虛擬列上的二級索引。

具體的說當(dāng)讀取到輔助索引里字段后再關(guān)聯(lián)到主鍵,對主鍵在內(nèi)存里進行排序后再順序的讀取其它字段的信息。這樣就會減少IO隨機讀。

InnoDB多范圍讀優(yōu)化(MRR)的主要應(yīng)用于沒有覆蓋索引的磁盤受限查詢(當(dāng)寫比讀快很多時,讀就即被認(rèn)為是磁盤受限)。

優(yōu)化參數(shù)

用optimizer_switch的參數(shù)來控制是否使用MRR.設(shè)置mrr=on時,表示啟用MRR優(yōu)化。

mrr_cost_based表示是否通過cost base的方式來啟用MRR。

當(dāng)mrr=on,mrr_cost_based=on,則表示cost base的方式還選擇啟用MRR優(yōu)化,當(dāng)發(fā)現(xiàn)優(yōu)化后的代價過高時就會不使用該項優(yōu)化。

當(dāng)mrr=on,mrr_cost_based=off,則表示總是開啟MRR優(yōu)化。

多訪問讀示例

mysql> EXPLAIN SELECT /*+ MRR(city) */ * FROM world.city WHERE CountryCode BETWEEN 'AUS' AND 'CHN'\G **************************** 1. row ***************************** id: 1 select_type: SIMPLE table: city partitions: NULL type: range possible_keys: CountryCode key: CountryCode key_len: 3 ref: NULL rows: 812 filtered: 100 Extra: Using index condition; Using MRR

批量鍵訪問Batched Key Access

批量鍵訪問概念

批量鍵值訪問(Batched Key Access)簡稱BKA,該優(yōu)化操作是塊內(nèi)嵌循環(huán)和多范圍讀的整合。這樣非索引聯(lián)接就可以使用類似連接緩沖區(qū)索引聯(lián)接的方式進行優(yōu)化,通過使用多范圍讀取優(yōu)化來減少隨機I/O的數(shù)量。

由于批處理鍵值訪問優(yōu)化主要受益的查詢范圍相對較窄,而且其他查詢的性能可能會下降,因此默認(rèn)情況下禁用優(yōu)化。

批量鍵訪問示例

SET SESSION optimizer_switch = 'mrr=on,mrr_cost_based=off,batched_key_access=on';mysql> EXPLAIN-> SELECT /*+ BKA(ci) */-> co.Code, co.Name AS Country,-> ci.Name AS City-> FROM world.country co-> INNER JOIN world.city ci-> ON ci.CountryCode = co.Code\G *************************** 1. row ***************************id: 1select_type: SIMPLEtable: copartitions: NULLtype: ALL possible_keys: PRIMARYkey: NULLkey_len: NULLref: NULLrows: 239filtered: 100.00Extra: NULL *************************** 2. row ***************************id: 1select_type: SIMPLEtable: cipartitions: NULLtype: ref possible_keys: CountryCodekey: CountryCodekey_len: 12ref: world.co.Coderows: 17filtered: 100.00Extra: Using join buffer (Batched Key Access)In this example, the Batched Key Access is enabled using an optimizer hint for the join on the city (ci) table using the CountryCode index

上例中通過優(yōu)化器提示(hint)啟用了批量鍵訪問選項,即在關(guān)聯(lián)city表時用到CountryCode索引。

批量鍵值范圍優(yōu)化主要應(yīng)用在數(shù)據(jù)量大的關(guān)聯(lián)中,關(guān)聯(lián)緩存則要相應(yīng)的設(shè)置的多些,一般它對應(yīng)的參數(shù)join_buffer_size要設(shè)置成4M或者更大。

總結(jié)

以上是生活随笔為你收集整理的MySQL 优化器之Index merge Multi-Range Read MRR与Batched Key Access使用案例详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。