成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

MySQL中數(shù)據(jù)庫哈希連接是怎樣的

MySQL中數(shù)據(jù)庫哈希連接是怎樣的,相信很多沒有經(jīng)驗的人對此束手無策,為此本文總結了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個問題。

創(chuàng)新互聯(lián)建站服務項目包括峽江網(wǎng)站建設、峽江網(wǎng)站制作、峽江網(wǎng)頁制作以及峽江網(wǎng)絡營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術優(yōu)勢、行業(yè)經(jīng)驗、深度合作伙伴關系等,向廣大中小型企業(yè)、政府機構等提供互聯(lián)網(wǎng)行業(yè)的解決方案,峽江網(wǎng)站推廣取得了明顯的社會效益與經(jīng)濟效益。目前,我們服務的客戶以成都為中心已經(jīng)輻射到峽江省份的部分城市,未來相信會繼續(xù)擴大服務區(qū)域并繼續(xù)獲得客戶的支持與信任!

概述

很長一段時間,MySQL 執(zhí)行 連接 的唯一算法是 嵌套循環(huán)算法 ( nested loop algorithm) 的變體 ,但是 嵌套循環(huán)算法 在某些場景下非常低效,也是 MySQL 一直被詬病的一個問題。

隨著 MySQL 8.0.18 的發(fā)布,MySQL Server 可以使用哈希連接(hash join),這篇文章將會簡單介紹下哈希連接如何實現(xiàn),看看在 MySQL 中它是如何工作的,何時使用它,有什么限制。

推薦學習:MySQL教程

哈希連接簡介

什么是哈希連接?

哈希連接是一種用于關系型數(shù)據(jù)庫中的連接算法,只能用于有等連接條件的連接中(on a.b = c.b)。它通常比 嵌套循環(huán) 算法 更高效(探測端非常非常小除外),尤其是在沒有命中索引的情況下。

簡單來說,哈希連接算法就是先把一張小表加載到內存哈希表里,然后遍歷大表的數(shù)據(jù),逐行去哈希表中匹配符合條件的數(shù)據(jù),返回到客戶端。

(哈希表只是示例,方面理解,實際 hash 的 key 是連接的值,value 是數(shù)據(jù)行鏈表)

通常將 哈希連接 分為兩個階段,構建階段(build phase)和探測階段(probe phase)。在構建階段,先選擇合適的表作為「構建輸入」,構建哈希表,然后再依次遍歷另一個「探測輸入」表記錄去探測哈希表查找符合連接條件的記錄。

以上圖為例,查詢城市對應的省份。我們假設 city 為 構建輸入,在構建階段,服務器構建一個 city 哈希 表 ,遍歷 city 表,將行依次放進 哈希表,鍵為 hash(province_id),值為對應的 城市行。`

在探測階段,服務器開始從 探測輸入(province) 讀取行。對于每一行都使用 hash(province.province_id) 值作為查找鍵探測哈希表以匹配行。

也就是,構建輸入能全部被加載到內存的情況下,僅掃每個探測行一次,使用常數(shù)時間查找就可以查找到兩個輸入之間匹配的行。

數(shù)據(jù)太多不能放入內存怎么辦?

將 構建輸入 全部加載到內存中無疑是效率最高的,但在有些情況下,內存不足以將整張表加載到內存中,就需要分批來處理。

常見的做法有兩種:

分批加載到內存處理

1.讀取最大內存可以容納的記錄創(chuàng)建哈希表 構建輸入 生成哈希表;

2.遍歷 探測輸入 對這部分哈希表進行一次全量探測;

3.清理掉哈希表重新進行這個流程,直至全部處理完成。

這種方式會導致探測輸入全表被掃描多次。

寫到文件處理

1.當在構建哈希表階段內存用完時,服務器將會把剩余的構建輸入寫到磁盤上的許多小文件中,小文件塊經(jīng)過計算可以全部被讀入內存并創(chuàng)建哈希表(避免文件塊太大后續(xù)無法加載到內存還需要再次分隔);

2.在探測階段,由于探測行可能與寫入磁盤的構建輸入的某行匹配,所以也需要將探測輸入寫入到磁盤中;

3.探測階段完成后,從磁盤讀取塊文件并加載到內存散列表中,再從探測輸入讀取響應的塊文件并探測匹配項;

4.處理完后,移動到下一對塊文件,直至全部處理完成。

MySQL 中的哈希連接實現(xiàn)

MySQL 會選擇兩個輸入中較小的一個作為構建輸入(以字節(jié)計算),在內存足夠的情況下將構建輸入加載到內存處理,不夠的情況下使用寫入文件的方式處理。

可以使用 join_buffer_size 系統(tǒng)變量控制 哈希連接 的內存使用,哈希連接 使用的內存不能超過這個數(shù)量,當超過這個數(shù)量時,MySQL 將使用文件來處理。

如果內存超過 join_buffer_size,并且文件超過 open_files_limit ,執(zhí)行可能失敗。

可以使用如下兩個解決方案:

● 增大 join_buffer_size 來避免 哈希連接 溢出到磁盤

● 增大 open_files_limit

MySQL 什么情況下會使用哈希連接?

在 MySQL 8.0.18 版本中,如果使用一個或多個等連接條件將表連接在一起,并且沒有可用于連接條件的索引,將使用哈希連接。如果索引可用,MySQL 傾向于使用索引查找來支持嵌套循環(huán)。

默認情況下,MySQL 會盡可能使用哈希連接 ,可以通過以下兩種方式啟用或關閉:

● 設置全局或 session 變量 (hash_join = on or hash_join = off);

SET optimizer_switch="hash_join=off";

● 使用 hints (HASH_JOIN or NO_HASH_JOIN)。

我們將使用以下查詢作為示例:

EXPLAIN FORMAT = tree
SELECT
  city.name AS city_name,
  province.name AS province_name
FROM
  city
  JOIN province
    ON city.province_id = province.province_id;

輸出為:

| -> Inner hash join (city.province_id = province.province_id)  (cost=1333.82 rows=1329)
    -> Table scan on city  (cost=0.14 rows=391)
    -> Hash
        -> Table scan on province  (cost=3.65 rows=34)

哈希連接 也可以用到多個 join 的查詢中,只要存在等值連接,就可以使用哈希連接。

例如以下查詢:

EXPLAIN FORMAT= TREE
SELECT
  city.name AS city_name,
  province.name AS province_name,
  country.name AS country_name
FROM
  city
  JOIN province
    ON city.province_id = province.province_id
    AND city.id < 50
  JOIN country
    ON province.province_id = country.id

輸出為:

| -> Inner hash join (city.province_id = country.id)  (cost=23.27 rows=2)
    -> Filter: (city.id < 50)  (cost=5.32 rows=5)
        -> Index range scan on city using PRIMARY  (cost=5.32 rows=49)
    -> Hash
        -> Inner hash join (province.province_id = country.id)  (cost=4.00 rows=3)
            -> Table scan on province  (cost=0.59 rows=34)
            -> Hash
                -> Table scan on country  (cost=0.35 rows=1)

哈希連接也同樣適用于 「笛卡爾積」,即沒有指定查詢條件,如下:

EXPLAIN FORMAT= TREE
SELECT
  *
FROM
  city
  JOIN province;

輸出為:

| -> Inner hash join  (cost=1333.82 rows=13294)
    -> Table scan on city  (cost=1.17 rows=391)
    -> Hash
        -> Table scan on province  (cost=3.65 rows=34)

MySQL 什么情況下不會使用哈希連接?

1.目前 MySQL 哈希連接只支持內連接,反連接、半連接和外連接仍然使用塊嵌套循環(huán)執(zhí)行。

2.如果索引可用,MySQL 會更傾向于使用索引查找來支持嵌套循環(huán);

3.當不存在等值查詢時,會使用嵌套循環(huán)。

如下:

EXPLAIN FORMAT=TREE
SELECT
  *
FROM
  city
  JOIN province
    ON city.province_id < province.province_id;

輸出為:

| <not executable by iterator executor>

如何查看語句執(zhí)行是否使用哈希連接?

EXPLAIN FORMAT= TREE 在 MySQL 8.0.16 及之后的版本可以使用,TREE 提供了類似于樹的輸出,對查詢處理的描述比傳統(tǒng)格式更加精確,它是唯一顯示 哈希連接 用法的格式。

除此之外,也可以使用 EXPLAIN ANALYZE 查看 哈希連接 信息。

看完上述內容,你們掌握MySQL中數(shù)據(jù)庫哈希連接是怎樣的的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!

本文標題:MySQL中數(shù)據(jù)庫哈希連接是怎樣的
網(wǎng)站網(wǎng)址:http://jinyejixie.com/article24/gpsjce.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站建設App設計、外貿(mào)網(wǎng)站建設網(wǎng)頁設計公司、微信小程序、網(wǎng)站改版

廣告

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

成都定制網(wǎng)站建設
喀喇沁旗| 偏关县| 济阳县| 新源县| 湖南省| 安达市| 漳浦县| 瑞金市| 含山县| 含山县| 垣曲县| 桑日县| 旬邑县| 新化县| 隆尧县| 威信县| 鹿邑县| 故城县| 囊谦县| 沂水县| 元朗区| 阳朔县| 海城市| 竹溪县| 吉木乃县| 田东县| 图木舒克市| 洱源县| 达拉特旗| 公安县| 乌鲁木齐县| 峨山| 绥中县| 赞皇县| 沂南县| 南召县| 曲阜市| 宜兰县| 连平县| 上饶市| 景洪市|