Mysql分组不使用索引

标签 mysql group-by indexing

给定:

CREATE TABLE `APPLICATION_DEVICE_PUSHINFO` (
  `applicationId` bigint(20) NOT NULL,
 `deviceId` bigint(20) NOT NULL,
 `active` bit(1) NOT NULL,
 `inactiveAsOf` datetime DEFAULT NULL,
 `lastSentOn` datetime DEFAULT NULL,
 `registeredOn` datetime DEFAULT NULL,
  `target` int(11) DEFAULT NULL,
 `token` varchar(4096) NOT NULL,
  PRIMARY KEY (`applicationId`,`deviceId`),
  KEY `FKE7F2D58285EFFEAA_idx` (`deviceId`),
  KEY `index3` (`token`(255)) USING BTREE,
  CONSTRAINT `FKE7F2D58285EFFEAA` FOREIGN KEY (`deviceId`) REFERENCES `DEVICES` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

如果我执行以下查询:

explain SELECT token FROM APPLICATION_DEVICE_PUSHINFO  group by token having count(deviceId) > 1;;

我得到:

'1', 'SIMPLE', 'APPLICATION_DEVICE_PUSHINFO', 'ALL', NULL, NULL, NULL, NULL, '7', 'Using temporary; Using filesort'

空值属于可能的键等。

为什么不使用列标记的索引?

最佳答案

由于您没有 WHERE 子句,查询需要处理所有行(注意 HAVING 子句在 GROUP BY 之后应用——因此它不限制要处理的行,只限制返回的行).

如果您无论如何都需要接触所有行,则很难从索引中获得任何好处。不过,如果您能够执行仅索引扫描 (IOS) 和/或从磁盘上的预购数据中获益,则有可能有所收获。

但是,IOS 可能(不确定 MySQL 是否考虑了 NOT NULL 约束)由于您访问 deviceId 列而被阻止,该列不包含在可能用于此的索引中查询(index3)。请注意,您需要拥有一个涵盖查询所有需求的索引才能获得仅索引扫描。然而,如果 MySQL 足够聪明并且识别 NOT NULL 约束,这应该不是问题。否则,重写您的查询。例如计数(*) > 1。

在这种特殊情况下,由于表的尺寸较小(至少根据优化器估计)(正如 Strawberry 已经提到的那样),您无论如何都有可能获得同样糟糕的 IOS。

如果您需要确保它也适用于更多行,只需填写表格并查看它是否更改了执行计划。如果不是,请按上述更改查询,然后重试。如果没有,请返回此处,我们会看到(发布新的执行计划)。

您希望通过索引执行此查询原则上是合理的。让它工作是另一回事:(

关于Mysql分组不使用索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20148997/

相关文章:

PHP MySQLi 如果 ID = 1 则回显行中的名称

postgresql - 使用 desc 在 postgresql 上创建索引时出错

sql - View 中的日期减法应该创建哪些索引?

t-sql - 添加新列只是为了拥有聚集表

尝试停止其服务时出现 MySQL-Linux 错误

php - PDO 库是否比原生 MySQL 函数更快?

mysql - 如何在 MySQL 中查找重复对

sql - 查找满足条件但不四舍五入的行的百分比

Mysql 从多个表中选择 sum() 和 group by

python - 重新索引错误 - python