如果varchar大小太大,为什么MySQL不使用索引?

jdzmm42g  于 2022-10-31  发布在  Mysql
关注(0)|答案(1)|浏览(170)

我正在连接一个表,注意到如果我连接的字段的varchar大小太大,那么MySQL就不会在连接中使用该字段的索引,从而导致查询时间明显延长。我在下面给出了解释和表定义。它是MySQL 5.7版本。知道为什么会发生这种情况吗?
表格定义:

CREATE TABLE `LotRecordsRaw` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `lotNumber` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `scrapingJobId` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `lotNumber_UNIQUE` (`lotNumber`),
  KEY `idx_Lot_lotNumber` (`lotNumber`)
) ENGINE=InnoDB AUTO_INCREMENT=14551 DEFAULT CHARSET=latin1;

解释道:

explain
(
  select lotRecord.*
  from LotRecordsRaw lotRecord
  left join (
    select lotNumber, max(scrapingJobId) as id
    from LotRecordsRaw
    group by lotNumber
  ) latestJob on latestJob.lotNumber = lotRecord.lotNumber
)

产生:

上面的屏幕截图显示了派生表没有使用“lotNumber”上的索引。在那个例子中,“lotNumber”字段是一个varchar(255)。如果我将其更改为一个较小的大小,例如varchar(45),那么解释查询将产生如下结果:

然后,查询的运行速度提高了几个数量级(2秒而不是100秒)。

t3irkdon

t3irkdon1#

万岁!你找到了一个优化的理由,不用盲目地在VARCHAR中使用255。
请试试191和192,我想知道这是不是分界线.
同时,我还有一些其他的意见:

  • UNIQUEKEY。也就是说,idx_Lot_lotNumber是冗余的,也可以删除。
  • Optimizer可以(并且可能会)使用INDEX(lotNumber, scrapingJobId)作为查找这些MAX的更快方法。
  • 不幸的是,没有办法指定“对lotNumber创建一个 unique 索引,但同时在索引中包含另一列”。
  • 等等!由于lotNumber是唯一的,因此每个lotNumber只有一行。这意味着MAXGROUP BY完全没有必要!
  • 看起来lotNumber可以升级为PRIMARY KEY(并完全摆脱id)。

相关问题