簡體   English   中英

為什么在添加新列后更改MySQL查詢執行計划?

[英]Why MySQL query execution plan changed after add new columns?

我有一張桌子和下面的一些數據:

-- MySQL dump 10.13  Distrib 5.7.17, for macos10.12 (x86_64)
--
-- Host: localhost    Database: testmysql
-- ------------------------------------------------------
-- Server version   5.7.17-log


--
-- Table structure for table `t_strange_index`
--

DROP TABLE IF EXISTS `t_strange_index`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;

CREATE TABLE `t_strange_index` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `status` tinyint(4) NOT NULL,
  `create_time` bigint(20) NOT NULL,
  PRIMARY KEY (`id`) USING BTREE,
  KEY `idx_time_status` (`create_time`,`status`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=21
       DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=COMPACT;

/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `t_strange_index`
--

LOCK TABLES `t_strange_index` WRITE;
/*!40000 ALTER TABLE `t_strange_index` DISABLE KEYS */;
INSERT INTO `t_strange_index` VALUES
        (1,1,1532745820825),(2,1,1532745864183),(3,1,1532745895207),
        (4,1,1532746773225),(5,1,1532746773225),(6,1,1532746773225),
        (7,1,1532746822078),(8,1,1532746822078),(9,1,1532746822078),
        (10,1,1532746979836),(11,1,1532746979836),(12,1,1532746979836),
        (13,9,1532763766641),(14,10,1532764510924),(15,10,1532765436500),
        (16,20,1532777350303),(17,9,1532777818806),(18,10,1532782628840),
        (19,10,1532782711973),(20,10,1532784164740);
/*!40000 ALTER TABLE `t_strange_index` ENABLE KEYS */;
UNLOCK TABLES;

然后獲取此SQL的查詢執行計划:

explain select * from t_strange_index
      where create_time >= 1532746822078
        and create_time <= 1532746979836
        and status = 1;

結果:

 id | select_type | table           | partitions | type  | possible_keys   | key             | key_len | ref  | rows | filtered | Extra                    
  1 | SIMPLE      | t_strange_index | NULL       | range | idx_time_status | idx_time_status | 9       | NULL |    6 |    10.00 | Using where; Using index 

但是在我添加新列之后

alter table t_strange_index add column `new column` bigint(20) NOT NULL default 123;

執行計划更改:

 id | select_type | table           | partitions | type | possible_keys   | key  | key_len | ref  | rows | filtered | Extra       
  1 | SIMPLE      | t_strange_index | NULL       | ALL  | idx_time_status | NULL | NULL    | NULL |   20 |     5.00 | Using where 

它不再使用索引了。

誰能告訴我為什么會這樣? 謝謝。

覆蓋指數

您應該注意到原來的EXPLAIN Extra具有Using Index。 這是覆蓋指數的指標。

覆蓋索引是包含查詢所需的所有列的索引。

當您添加新列時,idx_time_status不再是覆蓋索引(因為您選擇的是*且新列不在索引中),因此MySQL必須返回原始數據。 這就是為什么MySQL決定不使用索引效率更高的原因。

“覆蓋指數”只是故事的一部分。

這是倒退的:

  KEY `idx_time_status` (`create_time`,`status`) USING BTREE

索引從=測試開始,然后以范圍結束。 也就是說,此索引將更適合您的查詢:

  INDEX(status, create_time)

這將不必遍歷status != 1行; 索引將它們過濾掉。

但這並不能解釋索引的回避和切換到表掃描的原因。 這說明該范圍可能超過表的20%。 優化器會查看統計數據,並討論使用索引(僅需要幾行時)還是忽略索引並僅掃描表(需要多行時)會更快。

如果您的測試用例在給定范圍內有更多行,則可能具有不同的EXPLAIN

請參閱我的索引生成器食譜

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM