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

        共 9285字,需瀏覽 19分鐘

         ·

        2022-07-09 20:11

        不點(diǎn)藍(lán)字關(guān)注,我們哪來故事?



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

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

          MySQL的直方圖分為:等寬直方圖和等高直方圖,MySQL會(huì)自動(dòng)分配使用哪種類型的直方圖,無法干預(yù) 等寬直方圖:每個(gè)bucket保存一個(gè)值以及這個(gè)值的累計(jì)頻率

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

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

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

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

          創(chuàng)建語法

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

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

          刪除語法

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

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

          項(xiàng)目地址:https://github.com/YunaiV/ruoyi-vue-pro

          直方圖信息

          MySQL通過字典表column_statistics來保存直方圖的定義,每行記錄對(duì)應(yīng)一個(gè)字段的直方圖,已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字段分配了等高直方圖,默認(rèn)為100個(gè)bucket。

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

          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開始,存儲(chǔ)引擎自身提供了存儲(chǔ)在表中數(shù)據(jù)的采樣實(shí)現(xiàn),存儲(chǔ)引擎不支持時(shí),MySQL使用默認(rèn)采樣需要全表掃描,這樣對(duì)于大表來說成本太高,采樣實(shí)現(xiàn)避免了全表掃描提高采樣性能。

          通過INNODB_METRICS計(jì)數(shù)器可以監(jiān)視數(shù)據(jù)頁的采樣情況,這需要提前開啟計(jì)數(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)

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

          基于微服務(wù)的思想,構(gòu)建在 B2C 電商場(chǎng)景下的項(xiàng)目實(shí)戰(zhàn)。核心技術(shù)棧,是 Spring Boot + Dubbo 。未來,會(huì)重構(gòu)成 Spring Cloud Alibaba 。

          項(xiàng)目地址:https://github.com/YunaiV/onemall

          優(yōu)化案例

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

          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í)行計(jì)劃

          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



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


          長按二維碼,掃掃關(guān)注哦

          ?「C語言中文網(wǎng)」官方公眾號(hào),關(guān)注手機(jī)閱讀教程 ?

          瀏覽 52
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
            
            

              1. 操炮友| 肏逼视屏 | 91人妻人人澡人人爽人 | 黄片在线免费观 | 72式性无遮挡免费视频看片 |