MySQL前綴索引、臟頁和干凈頁、COUNT(*)討論、表刪除內存問題

文章目錄

  • 如何加索引
      • 如何給身份證號添加索引
  • SQL語句變慢
      • 臟頁 (Dirty Pages)
      • 干凈頁 (Clean Pages)
      • 為何區分臟頁和干凈頁
      • 處理臟頁
      • 管理策略
    • flush
      • 如何控制
  • 為什么刪除表數據后表文件大小不變
    • 問題背景
    • 核心原因
      • 數據存儲方式
      • 參數影響
    • 解決方案
      • 1. 調整`innodb_file_per_table`設置
      • 2. 使用表重建來回收空間
      • 3. 定期優化表
    • 注意事項
    • online和inplace
      • Inplace DDL
      • Online DDL
  • COUNT(*) 討論
    • `COUNT(*)` 的實現方式
    • InnoDB 的設計和挑戰
    • 解決策略
    • 建議
    • 總結

本文為mysql11-15講總結

如何加索引

MySQL是支持前綴索引的,也就是說,你可以定義字符串的一部分作為索引。默認地,如果你創建索引的語句不指定前綴長度,那么索引就會包含整個字符串。

mysql> alter table SUser add index index1(email);
或
mysql> alter table SUser add index index2(email(6));

第一個語句代表著以整個字符串作為索引,第二個則是只取前6個字節

第二種由于只取前6個字節所以占用空間更少,但是會增加額外的記錄掃描次數

如果使用的是index2(即email(6)索引結構),執行順序是這樣的:

  1. 從index2索引樹找到滿足索引值是’zhangs’的記錄,找到的第一個是ID1;

  2. 到主鍵上查到主鍵值是ID1的行,判斷出email的值不是’zhangssxyz@xxx.com,這行記錄丟棄;

  3. 取index2上剛剛查到的位置的下一條記錄,發現仍然是’zhangs’,取出ID2,再到ID索引上取整行然后判斷,這次值對了,將這行記錄加入結果集;

  4. 重復上一步,直到在index2上取到的值不是’zhangs’時,循環結束。

使用前綴索引時要定義好長度才能做到節省空間的同時盡可能減少增加的額外查詢成本

首先,你可以使用下面這個語句,算出這個列上有多少個不同的值:

mysql> select count(distinct email) as L from SUser;

然后,依次選取不同長度的前綴來看這個值,比如我們要看一下4~7個字節的前綴索引,可以用這個語句:

mysql> selectcount(distinct left(email,4)as L4,count(distinct left(email,5)as L5,count(distinct left(email,6)as L6,count(distinct left(email,7)as L7,
from SUser;

當然,使用前綴索引很可能會損失區分度,所以你需要預先設定一個可以接受的損失比例,比如5%。然后,在返回的L4~L7中,找出不小于 L * 95%的值,假設這里L6、L7都滿足,你就可以選擇前綴長度為6。

使用前綴索引比不上覆蓋索引對查詢性能的優化,就算將前綴索引的長度設置為字段長度,innodb也是會回到索引再查一遍

如何給身份證號添加索引

  1. 很多網頁比如說校園卡,會跟你說默認密碼為身份證后六位,所以我們也可以把身份證倒過來存儲,取六位為前綴索引
  2. 使用hash字段:在表上創建一個整數字段,保存身份證的校驗碼,同時創建索引
mysql> alter table t add id_card_crc int unsigned, add index(id_card_crc);

然后每次插入新記錄的時候,都同時用crc32()這個函數得到校驗碼填到這個新字段。由于校驗碼可能存在沖突,也就是說兩個不同的身份證號通過crc32()函數得到的結果可能是相同的,所以你的查詢語句where部分要判斷id_card的值是否精確相同。

mysql> select field_list from t where id_card_crc=crc32('input_id_card_string') and id_card='input_id_card_string'

這樣,索引的長度變成了4個字節,比原來小了很多。

接下來,我們再一起看看 使用倒序存儲和使用hash字段這兩種方法的異同點。

首先,它們的相同點是,都不支持范圍查詢。倒序存儲的字段上創建的索引是按照倒序字符串的方式排序的,已經沒有辦法利用索引方式查出身份證號碼在[ID_X, ID_Y]的所有市民了。同樣地,hash字段的方式也只能支持等值查詢。

它們的區別,主要體現在以下三個方面:

  1. 從占用的額外空間來看,倒序存儲方式在主鍵索引上,不會消耗額外的存儲空間,而hash字段方法需要增加一個字段。當然,倒序存儲方式使用4個字節的前綴長度應該是不夠的,如果再長一點,這個消耗跟額外這個hash字段也差不多抵消了。

  2. 在CPU消耗方面,倒序方式每次寫和讀的時候,都需要額外調用一次reverse函數,而hash字段的方式需要額外調用一次crc32()函數。如果只從這兩個函數的計算復雜度來看的話,reverse函數額外消耗的CPU資源會更小些。

  3. 從查詢效率上看,使用hash字段方式的查詢性能相對更穩定一些。因為crc32算出來的值雖然有沖突的概率,但是概率非常小,可以認為每次查詢的平均掃描行數接近1。而倒序存儲方式畢竟還是用的前綴索引的方式,也就是說還是會增加掃描行數。

SQL語句變慢

臟頁 (Dirty Pages)

  • 定義:內存中已被修改但尚未寫回磁盤的數據頁。
  • 重要性:允許數據庫延遲磁盤寫操作,提高性能。
  • 風險:系統崩潰時可能丟失未寫回的數據。

干凈頁 (Clean Pages)

  • 定義:內存中的數據頁內容與磁盤上的內容完全一致。
  • 優點:可以隨時從內存中移除而不影響數據完整性。
  • 場景:系統無需擔心數據丟失即可釋放這些數據頁。

為何區分臟頁和干凈頁

  1. 性能優化:允許數據頁在內存中保持臟狀態可以顯著提高數據庫的性能。這是因為磁盤I/O操作通常比內存操作要慢得多。通過減少必須執行的磁盤寫操作的次數,系統的整體響應時間和吞吐量可以得到提升。
  2. 事務的一致性和恢復:在發生系統崩潰或其他故障時,臟頁的存在是關鍵的,因為它們包含了重要的未持久化的數據。數據庫恢復機制(如日志重做)依賴于這些臟頁的信息來確保數據的一致性和完整性。
  3. 緩沖管理:數據庫系統通常包含一個緩沖池管理器,它負責決定何時讀取或寫入磁盤數據頁。通過智能地管理臟頁和干凈頁,緩沖池管理器可以優化數據訪問和寫回策略,例如使用LRU(最近最少使用)算法來決定哪些頁應當被保留在緩存中,哪些應當被寫回磁盤。

處理臟頁

數據庫通常通過一種稱為“檢查點”(checkpoint)的機制定期將所有臟頁寫回磁盤。這不僅有助于減少系統崩潰后恢復所需的時間,還可以確保數據的持久性和一致性。

總之,臟頁和干凈頁的概念是數據庫緩存管理的核心部分,對于理解和優化數據庫的性能和可靠性至關重要。

管理策略

  • 檢查點:定期將所有臟頁數據同步到磁盤,幫助減少數據恢復時間,確保數據一致性。
  • 緩沖池管理:有效管理臟頁和干凈頁,優化數據訪問和持久化策略。

flush

平時執行很快的更新操作,其實就是在寫內存和日志,而MySQL偶爾“抖”一下的那個瞬間,可能就是在刷臟頁(flush)。

flush:將臟頁寫入磁盤,確保持久性和一致性

引發flush的情況:

  1. 檢查點 (Checkpoint):數據庫定期執行檢查點操作,這是一個系統過程,旨在將所有當前的臟頁寫入磁盤。這樣做可以在系統崩潰后加快恢復速度,因為只需重新處理從最后一個檢查點之后的事務日志。
  2. 事務提交:當事務提交時,為保證數據的持久性,會觸發臟頁的寫入。這確保了一旦事務被標記為成功,它的更改就永久保存了。
  3. 臟頁的限制:如果臟頁的數量達到了數據庫系統設定的閾值,系統可能會自動觸發flush操作,以防內存中積累過多未寫入磁盤的更改。
  4. 內存壓力:當系統內存不足時,數據庫可能需要清空緩沖池中的頁,以為新的數據頁騰出空間。這種情況下,臟頁需要先被flush到磁盤,才能被清出內存。
  5. 系統關閉:在數據庫正常關閉過程中,為了確保所有暫存于內存中的更改都被持久化,會進行一次全面的flush操作。
  6. 手動觸發:數據庫管理員可以手動觸發flush操作,例如通過特定的SQL命令或數據庫管理工具,來管理數據庫的物理存儲情況。

如何控制

需要明確告訴innodb所在主機的io能力:

 fio -filename=$filename -direct=1 -iodepth 1 -thread -rw=randrw -ioengine=psync -bs=16k -size=500M -numjobs=10 -runtime=10 -group_reporting -name=mytest

關注臟頁比例,不要讓他經常接近75%,臟頁比例則是通過Innodb_buffer_pool_pages_dirty/Innodb_buffer_pool_pages_total得到的,具體的命令參考下面的代碼:

select VARIABLE_VALUE into @a from global_status where VARIABLE_NAME = 'Innodb_buffer_pool_pages_dirty';
select VARIABLE_VALUE into @b from global_status where VARIABLE_NAME = 'Innodb_buffer_pool_pages_total';
select @a/@b;

innodb_flush_neighbors在MySQL8.0中已經默認為0,這樣可以在如果鄰數據頁同為臟頁的情況下不被刷掉,也可以減少sql語句的響應時間

InnoDB刷臟頁速度策略|500

為什么刪除表數據后表文件大小不變

問題背景

在MySQL數據庫中,尤其是使用InnoDB存儲引擎的情況下,用戶經常遇到刪除表中大量數據后,表文件的物理大小沒有相應減小的問題。

核心原因

數據存儲方式

  • InnoDB存儲結構: InnoDB使用B+樹索引結構存儲數據,數據按頁(通常大小為16KB)組織。
  • 刪除操作的實際效果: 在InnoDB中,刪除操作僅標記數據行為刪除狀態,實際數據并未從磁盤中移除。這意味著物理空間不會立即釋放,而是留待將來重用。

參數影響

  • innodb_file_per_table:
    • 設置為OFF: 所有表數據存放在共享表空間(ibdata1文件)中,刪除數據后空間不會回收到操作系統,而是留在共享空間中待后續使用。
    • 設置為ON: 每個表數據存儲在單獨的.ibd文件中。雖然便于管理,但刪除表內數據或整表后,空間仍然不會自動縮減。

解決方案

1. 調整innodb_file_per_table設置

推薦將innodb_file_per_table設置為ON,以便每個表使用獨立的文件,便于管理和優化。

2. 使用表重建來回收空間

  • 重建單個表:

    ALTER TABLE your_table_name ENGINE=InnoDB;
    

    這個命令會重建表,期間移除了所有標記為刪除的記錄的空間,壓縮表中未使用的空間。

  • 創建新表并復制數據:

    CREATE TABLE new_table LIKE original_table;
    INSERT INTO new_table SELECT * FROM original_table;
    DROP TABLE original_table;
    RENAME TABLE new_table TO original_table;
    

    這種方法通過完全重建數據來優化存儲布局和頁的利用率。

3. 定期優化表

對于頻繁更新的表,定期執行表優化可以提高性能和空間利用率。

OPTIMIZE TABLE your_table_name;

注意事項

  • 操作風險: 重建表或優化表是資源密集型操作,可能會導致服務性能下降,特別是在高峰期進行這些操作時。建議在低峰時段進行,并確保有完整的備份。
  • 數據安全: 在進行任何結構修改前,確保備份所有重要數據,防止操作失誤導致數據丟失。

online和inplace

Inplace DDL

  • 定義: Inplace操作指的是在進行表結構變更時,數據不需要被移動到外部結構,而是在原有的表結構上直接進行修改。
  • 實現細節: 在InnoDB中,例如執行 ALTER TABLE 操作時,可能會創建一個臨時文件(tmp_file),這個文件用于處理數據重組過程。盡管操作在物理上看起來像是在原地進行(即不需要額外的臨時表),但實際上仍然需要額外的磁盤空間來存儲臨時數據。
  • 空間要求: 如果服務器的可用磁盤空間不足以創建所需的臨時文件,即使是inplace操作也無法完成。

Online DDL

  • 定義: Online DDL 允許在表結構變更過程中,表繼續對外提供服務,即允許對表進行讀寫操作。

  • 關系與區別: 所有Online DDL操作均是Inplace的,但并非所有Inplace操作都是Online的。例如,添加全文索引的過程雖然是inplace的,但它會阻塞表的寫操作,因此不是Online的。

  • Inplace but not Online: 例如,添加全文索引(FULLTEXT)或空間索引(SPATIAL),這些操作雖然在物理上不需要移動數據到新表,但會阻塞表的某些操作。

  • Online and Inplace: 某些表結構變更如增加新列或者修改某些不影響表數據排列的屬性,可以在線進行,同時在物理存儲上也是在原地完成。

以下是對您提供的文檔內容的總結和筆記:

COUNT(*) 討論

  • 問題討論:為什么在 MySQL 中使用 SELECT COUNT(*) FROM t 查詢表行數會隨著數據增多而變慢。
  • 焦點:分析 COUNT(*) 的執行機制,特別是在不同的存儲引擎(MyISAM 和 InnoDB)中的表現,并探討應對策略。

COUNT(*) 的實現方式

  • MyISAM:存儲行數在磁盤上,使得 COUNT(*) 很快,因為直接返回已存儲的數值。
  • InnoDB:需要逐行讀取數據并判斷行的可見性(MVCC),因此隨著數據量的增加,COUNT(*) 的性能會顯著下降。

InnoDB 的設計和挑戰

  • 多版本并發控制(MVCC):InnoDB 使用 MVCC 支持高并發,但這使得即使是簡單的 COUNT(*) 查詢也需要逐行檢視,以確定每行是否對查詢事務可見。
  • 索引優化:雖然 InnoDB 會嘗試通過遍歷最小的索引樹來優化 COUNT(*) 查詢,但這仍可能涉及大量數據處理。

解決策略

  1. 緩存系統(如 Redis):
    • 優點:快速讀寫。
    • 缺點:可能丟失更新,需要定期從數據庫同步來確保準確性。
  2. 定期同步:
    • 方法:定期從數據庫執行 COUNT(*) 并更新緩存。
    • 考量:平衡更新頻率和性能需求。

建議

  • 對于需要頻繁訪問數據行數的應用,推薦使用緩存系統維護計數,并結合定期同步策略以防數據丟失。
  • 需要權衡實時性和性能,選擇適合自己業務場景的數據同步頻率。

總結

  • 雖然 COUNT(*) 在 MyISAM 中非常快速,但不支持事務和并發控制,而 InnoDB 雖然支持高級功能,卻因為其數據一致性和并發控制設計,使得 COUNT(*) 變得較慢。
  • 在面對實際業務需求時,特別是在數據量大且更新頻繁的情況下,推薦采用外部緩存系統來處理計數,以提高性能。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/10966.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/10966.shtml
英文地址,請注明出處:http://en.pswp.cn/web/10966.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C#之三目運算、三元運算

三目運算也叫三元運算是一種簡單的條件語句,也稱為條件運算符。它可以根據一個表達式的結果確定另一個表達式的值。三目運算符使用“?”和“:”來表示。 注意使用bool值進行運算 三目運算符: 套路 三個空位 兩個符號 固定寫法 : 空位1 ? 空位2 : 空位3; 關鍵…

2024.5.8 —— LeetCode 高頻題復盤

目錄 檢測循環依賴7. 整數反轉LCR 170. 交易逆序對的總數55. 跳躍游戲45. 二叉樹的后序遍歷50. Pow(x, n)40. 組合總和 II74. 搜索二維矩陣26. 刪除有序數組中的重復項61. 旋轉鏈表 檢測循環依賴 題目鏈接 def haveCircularDependency(self, n: int, prerequisites):g [[]for…

MATLAB實現遺傳算法優化選址-路徑LRP問題(Location-Routing Problem)

MATLAB實現遺傳算法優化選址-路徑LRP問題(Location-Routing Problem) 一、模型 選址車輛路徑問題(Location-Routing Problem, LRP)是一個組合優化問題,旨在同時優化設施位置的選擇和車輛的配送路徑。在這個問題中,我們考慮一個由…

機器學習 - 決策樹

1. 決策樹基礎 定義與概念 決策樹是一種監督學習算法,主要用于分類和回歸任務。它通過學習從數據特征到輸出標簽的映射規則,構建一個樹形結構。在分類問題中,決策樹的每個葉節點代表一個類別。 案例分析 假設我們有一個關于天氣和是否進行…

linux防火墻的操作

linux防火墻的操作 前言1查看防火墻狀態2暫時關閉防火墻3永久關閉防火墻4開啟防火墻5開啟指定端口6關閉指定端口7立即生效8查看開放的端口前言 systemctl是管理linux中服務的命令,可以對服務進行啟動、停止、重啟、查看狀態等操作 firewall-cmd是linux中專門用于控制防火墻的…

并發-守護線程setDaemon()

目錄 為什么存在 什么是守護線程 創建守護線程 在使用守護線程時需要注意以下幾點 可以使用isDaemon()方法來檢查線程是否是守護線程 例1:上面提到當JVM中只剩下守護線程的時候,JVM就會退出,那么寫段代碼測試下 例2:thread…

小紅的字符串構造和小紅的排列構造

小紅的字符串構造 小紅希望你構造一個長度為nnn的、僅包含小寫字母的字符串,其中恰好有kkk個長度大于1的回文子串。你能幫幫她嗎?輸入兩個整數n,k,用空格隔開。 1≤n≤10^5,0≤k≤n/2.一個字符串。如果有多解輸出任意即可。 可以證明&#x…

[Bug]:由于中國防火墻,無法連接 huggingface.co

問題描述 : OSError: We couldnt connect to https://huggingface.co to load this file, couldnt find it in the cached files and it looks like youscan/ukr-roberta-base is not the path to a directory containing a file named config. Json. Checkout your internet …

[AIGC] 幾道 redis數據結構相關面試題

文章目錄 7. 數據類型的實現8. 什么是空間預分配以及惰性空間釋放,SDS 是怎么實現的9. 為什么說 SDS 是二進制安全的呢10. 說說 redis 里的對象11. 使用 RedisObject 的好處12. RedisObject 的具體結構是什么 7. 數據類型的實現 8. 什么是空間預分配以及惰性空間釋放…

Vue3實戰筆記(16)—pinia基本用法--Getter

文章目錄 前言一、pinia的getter簡單理解二、訪問其他 store 的 getter總結 前言 在 Pinia 中,getter 類似于 Vuex 中的 getter,允許你從 store 中派生出一些狀態,而不需要修改原始狀態。這使得我們可以創建基于現有狀態的計算屬性。 一、pi…

練習題(2024/5/12)

1二分查找 給定一個 n 個元素有序的(升序)整型數組 nums 和一個目標值 target ,寫一個函數搜索 nums 中的 target,如果目標值存在返回下標,否則返回 -1。 示例 1: 輸入: nums [-1,0,3,5,9,12], target 9 輸出: 4…

樹莓派C語言開發

安裝C語言編譯器和開發工具 sudo apt update sudo apt install build-essential 此命令會安裝GCC編譯器以及make等其他工具,這些都是C語言程序開發過程中必需的。 配置文本編輯器 樹莓派默認安裝了幾個文本編輯器,如Nano和Vim。如果你對這些編輯器不熟…

如何遠程訪問?

遠程訪問是指在不同的地理位置之間通過網絡連接來實現對目標設備或系統的訪問。無論是在個人生活還是商業領域,遠程訪問都起到了重要的作用,幫助人們實現高效的工作和便捷的生活。本文將介紹一款名為【天聯】的組網產品,它是一款強大的異地組…

Linux與Windows互傳文件【筆記】

Linux與Windows互傳文件【筆記】 前言前言推薦Linux與Windows互傳文件首先確保Windows安裝ssh如何傳送文件問題 最后 前言 這是陳舊已久的草稿2023-05-10 00:01:24 這個是準備把計組課程華為智能計組的,傳輸文件。 最后發現,好像沒有實現了。 現在202…

汽車線控轉向系統介紹

汽車線控轉向系統由方向盤總成、轉向執行總成和主控制器(ECU)三個主要部分以及自動防故障系統、電源等輔助系統組成。 線控轉向系統(Steering-By-Wire),取消了方向盤和轉向車輪之間的機械連接部件,徹底擺脫了機械固件的限制,完全由電能來實現…

【LeetCode】數組——hashmap的妙用

在遇到一類題目時,通過雙for循環也可暴力破解,但我們可以通過用hashmap來代替一次for循環節約時間開支,在算法上屬于用空間換時間,也能幫助我們更好的理解hashmap這一種重要數據結構,并熟悉hashmap的重要方法。 1.兩數…

31Windows精簡系統下載推薦

Windows精簡系統下載推薦 世界上有很多人在做Windows精簡系統,去掉了他們認為不必要的功能和插件,達到了減小系統安裝包體積,提升系統運行流暢度和穩定性的目的。 筆者推薦使用大佬不忘初心制作的精簡版系統,最精簡windows10系統安…

什么是數據平臺——企業構建Data+AI的基礎數據底座需要的決策參考

什么是數據平臺 標準的解釋是這樣的 Wikipedia A data platform usually refers to a software platform used for collecting and managing data, and acting as a data delivery point for application and reporting software. 數據平臺是指將各類數據進行整合、存儲、處…

你知道C++多少——默認成員函數

🌈個人主頁:小新_- 🎈個人座右銘:“成功者不是從不失敗的人,而是從不放棄的人!”🎈 🎁歡迎各位→點贊👍 收藏?? 留言📝 🏆所屬專欄&#xff1…

Python vs MATLAB:選擇深度學習的首選編程語言

Python vs MATLAB:選擇深度學習的首選編程語言 在深度學習領域,編程語言的選擇對于初學者的學習路徑和未來的職業發展至關重要。目前,Python和MATLAB都是進行科學計算和數據分析的流行工具,但它們在深度學習社區中的應用和受歡迎…