查詢優化器負責將SQL查詢轉換為盡可能高效的執行計劃,但隨著數據環境不斷變化,查詢優化器可能無法找到最佳的執行計劃,導致SQL效率低下。造成這種情況的原因是優化器對查詢的數據了解的不夠充足,例如:每個表有多少行數據,每列中有多少不同的值,每列的數據分布情況。
因此MySQL8.0.3推出了直方圖(histogram)功能,直方圖是列的數據分布的近似值,其向優化器提供更多的統計信息。比如字段的個數,每個不同值的百分比,最大/最小值等。MySQL的直方圖分為:等寬直方圖和等高直方圖,MySQL會自動分配使用哪種類型的直方圖,無法幹預
直方圖同時也存在壹定的限制條件:
創建和刪除直方圖
創建語法
創建直方圖時能夠同時為多個列創建直方圖,但必須指定bucket數量,範圍在1-1024之間,默認100。對於bucket數量應該綜合考慮其有多少不同值、數據的傾斜度、精度等,建議從較低的值開始,不符合再依次增加。
刪除語法
直方圖信息
MySQL通過字典表column_statistics來保存直方圖的定義,每行記錄對應壹個字段的直方圖,已JSON格式保存。
MySQL為employees的first_name字段分配了等高直方圖,默認為100個bucket。
當生成直方圖時,MySQL會將所有數據都加載到內存中,並在內存中執行所有工作。如果在大表上生成直方圖,可能會將幾百M的數據讀取到內存中的風險,因此我們可以通過參數 hitogram_generation_max_mem_size 來控制生成直方圖最大允許的內存量,當指定內存滿足不了所有數據集時就會采用采樣的方式。
從MySQL8.0.19開始,存儲引擎自身提供了存儲在表中數據的采樣實現,存儲引擎不支持時,MySQL使用默認采樣需要全表掃描,這樣對於大表來說成本太高,采樣實現避免了全表掃描提高采樣性能。
通過INNODB_METRICS計數器可以監視數據頁的采樣情況,這需要提前開啟計數器
采樣率的計算公式為: sampled_page_read/(sampled_pages_read + sampled_pages_skipped)
優化案例
復制壹張表出來,源表不添加直方圖,新表添加直方圖
分別在兩張表上查看SQL的執行計劃
可以看出Cost值從30214.45降到了18744.56,掃描行數從299822降到了41654,性能有所提升