成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Explain 顯示 Count(*) 使用了索引,實際卻是全表掃描

數據庫 MySQL
從 8.0.17(含)版本開始,直到目前的最新版本(8.0.33),如果表中有二級索引,explain 輸出的執行計劃也表示會使用二級索引,然而,實際執行過程中,InnoDB 卻會強制進行全表掃描,以使用主鍵索引的并行掃描能力。

這篇文章依然源于一位讀者的提問:explain 顯示 count(*) 使用了索引,optimizer trace 卻顯示為全表掃描,這是為什么?

還記得當時調試源碼的過程中,如果 explain 顯示會使用二級索引進行全索引掃描,執行時也確實只會從二級索引中讀取記錄,不會進行全表掃描。

不過,那會沒有關注過 optimizer trace 是怎么顯示的。

既然不能從記憶里找到答案,那就只能從源碼里找答案了。

擼完源碼發現:和 5.7.35 版本相比,8.0.32 的 count(*) 實現邏輯,確實有了一些變化。

接下來,我們一起來看看。

本文基于 MySQL 8.0.32 源碼,存儲引擎為 InnoDB。如需轉載,請聯系『一樹一溪』公眾號作者。

1、準備工作

創建測試表:

CREATE TABLE `t1` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `i1` int DEFAULT '0',
  PRIMARY KEY (`id`) USING BTREE,
  KEY `idx_i1` (`i1`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3

插入數據:

INSERT INTO `t1`(`id`, `i1`)
VALUES (10, 101), (20, 201), (30, 301);

2、問題重現及分析

explain 查看執行計劃:

EXPLAIN SELECT COUNT(*) FROM `t1`;

結果如下(只截取了部分字段):

圖片圖片

再來看看 optimizer trace 描述的執行計劃,依次執行以下 3 條 SQL:

-- 開啟 optimizer trace
SET optimizer_trace = "enabled=on";

-- 執行 SELECT 語句
SELECT COUNT(*) FROM `t1`;

-- 獲取 optimizer trace
SELECT * FROM information_schema.optimizer_trace;

結果如下(只截取了部分內容):

{
  "considered_execution_plans": [
    {
      "plan_prefix": [
      ],
      "table": "`t1`",
      "best_access_path": {
        "considered_access_paths": [
          {
            "rows_to_scan": 3,
            "access_type": "scan",
            "resulting_rows": 3,
            "cost": 0.55,
            "chosen": true
          }
        ]
      },
      "condition_filtering_pct": 100,
      "rows_for_plan": 3,
      "cost_for_plan": 0.55,
      "chosen": true
    }
  ]
}

我們來對比下 explain 和 optimizer trace 的結果:

  • explain 輸出結果中,type 字段值為 index、key 字段值為 idx_i1,表示會使用 idx_i1 作為覆蓋索引執行 select 語句。由于沒有 where 條件,select 語句會對二級索引 idx_i1 進行全索引掃描,以獲取 t1 表的記錄數量。
  • optimizer trace 輸出結果中,沒有顯示會使用索引 idx_i1,而且,access_type 為 scan,看起來像是會進行全表掃描。

我在 5.7.35 中調試了這條 SQL:

SELECT COUNT(*) FROM `t1`

可以證實,select 語句執行過程中,確實對 idx_i1 進行了全索引掃描,和 explain 輸出的執行計劃一致。

同時也確認了:不管是對主鍵索引進行全索引掃描(也就是全表掃描),還是對二級索引進行全索引掃描,optimizer trace 的輸出結果中,access_type 字段值都是 scan。

我又在 8.0.32 中調試了上面的 SQL,發現了新情況:InnoDB 對不包含 where 條件的 select count(*) from table 語句進行了特殊處理。

跟隨調試過程,我們一起來看看 InnoDB 做了什么特殊處理。

程序執行到 ha_records() 方法時,我們可以看到,index 參數的值是 1,這就是執行計劃確定要使用的索引 ID。

圖片圖片

我們在調試控制臺打印索引名字,可以看到 ID = 1 的索引就 idx_i1:

圖片圖片

ha_records() 會調用 records_from_index(),代碼如下:

圖片圖片

從以上代碼可以看到,ha_records() 把索引 idx_i1 的 ID 傳給了 records_from_index() 的第 2 個參數,但是,該方法的第 2 個參數,只有類型(uint),沒有名字,這說明第 2 個參數不能被使用。

也就是說,雖然執行計劃確定了要使用索引 idx_i1 來統計 t1 表的記錄數量,records_from_index() 卻沒有真正使用 idx_i1。

從代碼注釋也可以看到:在實現二級索引的并行掃描之前,records_from_index() 會強制使用主鍵索引來統計表中的記錄數量。

在 github 中追溯代碼提交歷史,發現 records_from_index() 是 8.0.17 版本新加的。

從這個版本開始,到最新的 8.0.33,對于不包含 where 條件的 select count(*) from table 語句,都會強制使用主鍵索引(也就是會進行全表掃描)。

之所以這么做,是為了使用多個線程對主鍵索引進行并行掃描,以提升執行速度。

3、總結

雖然本文內容比較短,但是本著完整的原則,還是進行個簡單的總結:

  • 8.0.16(含)版本之前,對于 select count(*) from table 語句,如果表中有二級索引,InnoDB 會選擇對某個二級索引進行全索引掃描,以獲取表中的記錄數量。
  • 從 8.0.17(含)版本開始,直到目前的最新版本(8.0.33),如果表中有二級索引,explain 輸出的執行計劃也表示會使用二級索引,然而,實際執行過程中,InnoDB 卻會強制進行全表掃描,以使用主鍵索引的并行掃描能力。
  • optimizer trace 的結果中,對于 select count(*) from table 語句,二級索引的全索引掃描和全表掃描同等對待,執行計劃的 access_type 字段值都是 scan。
責任編輯:姜華 來源: 一樹一溪
相關推薦

2010-04-27 17:02:18

Oracle EXPL

2022-12-05 08:35:06

MySQL計算讀取

2010-05-19 10:37:06

MySQL expla

2017-09-05 12:44:15

MySQLSQL優化覆蓋索引

2024-10-28 08:34:06

2011-08-24 17:23:10

2011-08-24 15:11:15

explain中文man

2023-02-26 01:00:12

索引優化慢查詢

2010-04-28 17:14:38

Oracle EXPL

2018-04-04 12:05:04

Postgre數據planner

2010-04-14 16:45:29

Oracle 9i全索

2020-08-10 11:20:59

索引MySQL數據庫

2009-11-11 09:40:53

Oracle索引掃描

2009-11-10 17:27:01

Oracle全表掃描

2010-04-14 16:22:42

Oracle 9i

2019-07-29 09:42:56

索引死鎖MySQL

2010-10-12 13:55:41

MySQL EXPLA

2022-11-05 08:37:00

MySQL數據索引

2021-09-16 06:44:07

數據庫SQL語句

2009-11-11 09:13:11

Oracle索引掃描
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日韩在线| 国产一区三区在线 | 精品国产不卡一区二区三区 | 日韩欧美在线一区 | 日日夜夜精品视频 | 久久久精品久久 | 91av视频 | 日韩欧美中文在线 | 午夜精品一区二区三区在线视频 | 欧美综合在线视频 | 国产91视频播放 | 久久久99精品免费观看 | 欧美精品在线一区 | 国产高清在线观看 | 久久黄色网 | 国产精品久久久久久久白浊 | 羞羞视频网站在线观看 | 久久99这里只有精品 | 久久精品网| 免费看a| 亚洲视频免费在线播放 | 欧洲精品在线观看 | 中文字幕av在线一二三区 | 国产一级免费视频 | 伊人久久成人 | 又爽又黄axxx片免费观看 | 亚洲精品黄 | 盗摄精品av一区二区三区 | 亚洲 一区 | 国产精品久久久久久福利一牛影视 | 亚洲精品视 | 毛片一级片 | 精品一区欧美 | 少妇一区二区三区 | 日韩精品一区二区三区 | 久久国产精品久久国产精品 | 中文字幕高清av | 日本五月婷婷 | 久久一区二区免费视频 | 国产精品欧美一区二区三区 | ww 255hh 在线观看 |