<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          MySQ 8.0 推出直方圖,性能大大提升!

          共 9285字,需瀏覽 19分鐘

           ·

          2022-07-09 20:11

          不點藍字關注,我們哪來故事?



            查詢優(yōu)化器負責將SQL查詢轉換為盡可能高效的執(zhí)行計劃,但隨著數(shù)據環(huán)境不斷變化,查詢優(yōu)化器可能無法找到最佳的執(zhí)行計劃,導致SQL效率低下。造成這種情況的原因是優(yōu)化器對查詢的數(shù)據了解的不夠充足,例如:每個表有多少行數(shù)據,每列中有多少不同的值,每列的數(shù)據分布情況。

            因此MySQL8.0.3推出了直方圖(histogram)功能,直方圖是列的數(shù)據分布的近似值,其向優(yōu)化器提供更多的統(tǒng)計信息。比如字段NULL的個數(shù),每個不同值的百分比,最大/最小值等。

            MySQL的直方圖分為:等寬直方圖和等高直方圖,MySQL會自動分配使用哪種類型的直方圖,無法干預 等寬直方圖:每個bucket保存一個值以及這個值的累計頻率

            • 等高直方圖:每個bucket保存不同值的個數(shù),上下限以及累計頻率

            直方圖同時也存在一定的限制條件:

            • 不支持幾何類型以及json類型的列
            • 不支持加密表和臨時表
            • 無法為單列唯一索引的字段生成直方圖

            創(chuàng)建和刪除直方圖

            創(chuàng)建語法

            ANALYZE TABLE tbl_name UPDATE HISTOGRAM ON col_name [, col_name] WITH N BUCKETS;

            創(chuàng)建直方圖時能夠同時為多個列創(chuàng)建直方圖,但必須指定bucket數(shù)量,范圍在1-1024之間,默認100。對于bucket數(shù)量應該綜合考慮其有多少不同值、數(shù)據的傾斜度、精度等,建議從較低的值開始,不符合再依次增加。

            刪除語法

            ANALYZE TABLE tbl_name DROP HISTOGRAM ON col_name [, col_name];

            基于 Spring Boot + MyBatis Plus + Vue & Element 實現(xiàn)的后臺管理系統(tǒng) + 用戶小程序,支持 RBAC 動態(tài)權限、多租戶、數(shù)據權限、工作流、三方登錄、支付、短信、商城等功能。

            項目地址:https://github.com/YunaiV/ruoyi-vue-pro

            直方圖信息

            MySQL通過字典表column_statistics來保存直方圖的定義,每行記錄對應一個字段的直方圖,已JSON格式保存。

            root@employees 13:49:  select json_pretty(histogram) from information_schema.column_statistics where table_name='employees' and column_name='first_name';;
            {
              "buckets": [
                [
                  "base64:type254:QWFtZXI=",
                  "base64:type254:QWRlbA==",
                  0.010176045588684237,
                  13
                ],
              "data-type""string",
              "null-values"0.0,
              "collation-id"255,
              "last-updated""2020-09-09 05:47:32.548874",
              "sampling-rate"0.163495700259278,
              "histogram-type""equi-height",
              "number-of-buckets-specified"100
            }

            MySQL為employees的first_name字段分配了等高直方圖,默認為100個bucket。

            當生成直方圖時,MySQL會將所有數(shù)據都加載到內存中,并在內存中執(zhí)行所有工作。如果在大表上生成直方圖,可能會將幾百M的數(shù)據讀取到內存中的風險,因此我們可以通過參數(shù)hitogram_generation_max_mem_size來控制生成直方圖最大允許的內存量,當指定內存滿足不了所有數(shù)據集時就會采用采樣的方式。

            root@employees 14:12:  select histogram->>'$."sampling-rate"' from information_schema.column_statistics where table_name='employees' and column_name='first_name';;
            +---------------------------------+
            | histogram->>'$."sampling-rate"' |
            +---------------------------------+
            | 0.163495700259278               |
            +---------------------------------+

            從MySQL8.0.19開始,存儲引擎自身提供了存儲在表中數(shù)據的采樣實現(xiàn),存儲引擎不支持時,MySQL使用默認采樣需要全表掃描,這樣對于大表來說成本太高,采樣實現(xiàn)避免了全表掃描提高采樣性能。

            通過INNODB_METRICS計數(shù)器可以監(jiān)視數(shù)據頁的采樣情況,這需要提前開啟計數(shù)器

            root@employees 14:26:  SELECT NAMECOUNT FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME LIKE 'sampled%'\G
            *************************** 1. row ***************************
             NAME: sampled_pages_read
            COUNT430
            *************************** 2. row ***************************
             NAME: sampled_pages_skipped
            COUNT456
            2 rows in set (0.04 sec)

            采樣率的計算公式為:sampled_page_read/(sampled_pages_read + sampled_pages_skipped)

            基于微服務的思想,構建在 B2C 電商場景下的項目實戰(zhàn)。核心技術棧,是 Spring Boot + Dubbo 。未來,會重構成 Spring Cloud Alibaba 。

            項目地址:https://github.com/YunaiV/onemall

            優(yōu)化案例

            復制一張表出來,源表不添加直方圖,新表添加直方圖

            root@employees 14:32:  create table employees_like like employees;
            Query OK, 0 rows affected (0.03 sec)

            root@employees 14:33:  insert into employees_like select * from employees;
            Query OK, 300024 rows affected (3.59 sec)
            Records: 300024  Duplicates: 0  Warnings: 0

            root@employees 14:33:  ANALYZE TABLE employees_like update HISTOGRAM on birth_date,first_name;
            +--------------------------+-----------+----------+-------------------------------------------------------+
            | Table                    | Op        | Msg_type | Msg_text                                              |
            +--------------------------+-----------+----------+-------------------------------------------------------+
            | employees.employees_like | histogram | status   | Histogram statistics created for column 'birth_date'. |
            | employees.employees_like | histogram | status   | Histogram statistics created for column 'first_name'. |
            +--------------------------+-----------+----------+-------------------------------------------------------+

            分別在兩張表上查看SQL的執(zhí)行計劃

            root@employees 14:43:  explain format=json select count(*) from employees where (birth_date between '1953-05-01' and '1954-05-01') and first_name like 'A%';
            {
              "query_block": {
                "select_id"1,
                "cost_info": {
                  "query_cost""30214.45"
                },
                "table": {
                  "table_name""employees",
                  "access_type""ALL",
                  "rows_examined_per_scan"299822,
                  "rows_produced_per_join"3700,
                  "filtered""1.23",
                  "cost_info": {
                    "read_cost""29844.37",
                    "eval_cost""370.08",
                    "prefix_cost""30214.45",
                    "data_read_per_join""520K"
                  },
                  "used_columns": [
                    "birth_date",
                    "first_name"
                  ],
                  "attached_condition""((`employees`.`employees`.`birth_date` between '1953-05-01' and '1954-05-01') and (`employees`.`employees`.`first_name` like 'A%'))"
                }
              }
            }

            root@employees 14:45:  explain format=json select count(*) from employees where (birth_date between '1953-05-01' and '1954-05-01') and first_name like 'A%';
            {
              "query_block": {
                "select_id"1,
                "cost_info": {
                  "query_cost""18744.56"
                },
                "table": {
                  "table_name""employees",
                  "access_type""range",
                  "possible_keys": [
                    "idx_birth",
                    "idx_first"
                  ],
                  "key""idx_first",
                  "used_key_parts": [
                    "first_name"
                  ],
                  "key_length""58",
                  "rows_examined_per_scan"41654,
                  "rows_produced_per_join"6221,
                  "filtered""14.94",
                  "index_condition""(`employees`.`employees`.`first_name` like 'A%')",
                  "cost_info": {
                    "read_cost""18122.38",
                    "eval_cost""622.18",
                    "prefix_cost""18744.56",
                    "data_read_per_join""874K"
                  },
                  "used_columns": [
                    "birth_date",
                    "first_name"
                  ],
                  "attached_condition""(`employees`.`employees`.`birth_date` between '1953-05-01' and '1954-05-01')"
                }
              }
            }

            可以看出Cost值從30214.45降到了18744.56,掃描行數(shù)從299822降到了41654,性能有所提升。


            END



            若覺得文章對你有幫助,隨手轉發(fā)分享,也是我們繼續(xù)更新的動力。


            長按二維碼,掃掃關注哦

            ?「C語言中文網」官方公眾號,關注手機閱讀教程 ?

            瀏覽 52
            點贊
            評論
            收藏
            分享

            手機掃一掃分享

            分享
            舉報
            評論
            圖片
            表情
            推薦
            點贊
            評論
            收藏
            分享

            手機掃一掃分享

            分享
            舉報
            <kbd id="afajh"><form id="afajh"></form></kbd>
            <strong id="afajh"><dl id="afajh"></dl></strong>
              <del id="afajh"><form id="afajh"></form></del>
                  1. <th id="afajh"><progress id="afajh"></progress></th>
                    <b id="afajh"><abbr id="afajh"></abbr></b>
                    <th id="afajh"><progress id="afajh"></progress></th>
                    尹人在线大香蕉 | 18禁天堂 | 超碰在线免费大屁股导航 | 国产在线播放三区 | 久久综合导航 |