mysql 为什么显示索引时基数变为1?

inkz8wg9  于 2023-03-07  发布在  Mysql
关注(0)|答案(1)|浏览(213)

最初,数据库监控平台的SQL警报速度很慢。

SELECT * FROM t1 WHERE deduct_status = 1 AND bill_date = '2023-02-15' AND type IN (1, 2) AND gs_id IN (794872, 794873, 794874, 794875, 532720, 794868, 794869, 794870, 794871, 794864);

我首先查询了这个表的信息。表的结构如下。我省略了一些无关的敏感字段和注解。

CREATE TABLE `t1` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`gs_id` int(10) NOT NULL,
`bill_date` date NOT NULL ,
`account_user_id` bigint(20) NOT NULL DEFAULT '0',
`type` tinyint(2) NOT NULL DEFAULT '-1' ,
`bill_count` int(10) NOT NULL DEFAULT '0' ,
`deduct_status` tinyint(2) NOT NULL DEFAULT '0',
`deduct_amount` decimal(10, 2) NOT NULL DEFAULT '0.00',
`version` int(10) NOT NULL DEFAULT '0',
`gmt_create` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`creator` varchar(50) NOT NULL DEFAULT '' ,
`gmt_modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_gsid_billdate_type_accountid` (`gs_id`, `bill_date`, `type`, `account_user_id`)
) ENGINE = InnoDB AUTO_INCREMENT = 377270771 DEFAULT CHARSET = utf8mb4

正常情况下,此SQL将通过唯一索引uk_gsid_billdate_type_accountid进行查询。
所以,我想可能是索引有问题,导致mysql的优化器选择不按索引查询。
然后我执行了下面的sql。

show INDEX from t1;

执行结果如下,我隐藏了表名:

以下是我认为有用的一些其他信息:

SELECT index_name, stat_name, stat_value, stat_description
       FROM mysql.innodb_index_stats WHERE table_name like 't1';

show variables like 'innodb_stats%';

select  version();

我想知道为什么基数是1,这是否是sql慢的原因。
过了一个晚上,我重新执行了这个sql,这个表恢复了正常,我什么都没做。

show INDEX from t1;

soat7uwm

soat7uwm1#

该索引可能以低基数gs_id开始。此外,该列未使用=进行测试,因此优化程序将通过gs_id

WHERE deduct_status = 1
  AND bill_date = '2023-02-15'
  AND type IN (1, 2)
  AND gs_id IN (794872, 794873, ...)

最佳索引类似于:

INDEX(deduct_status, bill_date,   -- either order is OK
      type, gs_id)                -- again, either order

即便如此,前2列的基数可能不足以保证使用索引。
运行ANALYZE TABLE t1;;它 * 可以 * 更新基数。

相关问题