【问题标题】:Strange MySQL index used使用了奇怪的 MySQL 索引
【发布时间】:2019-04-05 18:38:27
【问题描述】:

我使用的是 MySQL 8,但我仍然对如何选择用于不同查询的索引有一些疑问

表格如下:

CREATE TABLE IF NOT EXISTS `collection_stats` (
  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  `date` DATE NOT NULL,
  `org_uuid` BINARY(16) NOT NULL,
  `project_uuid` BINARY(16) NOT NULL,
  `collection_name` VARCHAR(255) NOT NULL,
  `counter1` BIGINT UNSIGNED NOT NULL DEFAULT 0,
  `counter2` BIGINT UNSIGNED NOT NULL DEFAULT 0,
  `counter3` BIGINT UNSIGNED NOT NULL DEFAULT 0,
  PRIMARY KEY (`id`),
  INDEX `date_index` (`date` ASC),
  INDEX `org_usage_index` (`org_uuid` ASC, `date` DESC),
  INDEX `project_usage_index` (`org_uuid` ASC, `project_uuid` ASC, `date` DESC),
  UNIQUE INDEX `collection_usage_index` (`org_uuid` ASC, `project_uuid` ASC, `collection_name` ASC, `date` DESC))
ENGINE = InnoDB;

想法是我有一些按组织、项目、集合组织的日常统计数据(一个组织可以有多个项目,一个项目可以有多个集合)。

我想查看过去 X 天内每个组织、每个项目或每个集合的 counter1counter 2counter 3 的值。

获取组织的统计信息:

explain SELECT 
    org_uuid, project_uuid, collection_name, 
    counter1, counter2, counter3 
FROM collection_stats 
WHERE 
    org_uuid = UUID_TO_BIN('bb5c2330-1a85-11e9-8ad9-b728a2ed4173', 1)  AND 
    date >= DATE_SUB(NOW(), INTERVAL 10 DAY)
# id, select_type, table, partitions, type, possible_keys, key, key_len, ref, rows, filtered, Extra
'1', 'SIMPLE', 'collection_stats', NULL, 'ref', 'collection_usage_index,date_index,org_usage_index,project_usage_index', 'collection_usage_index', '16', 'const', '8', '100.00', 'Using index condition'

我看到它使用的是collection_usage_index 而不是org_usage_index,但我对此没有任何解释。

获取项目级别的统计数据

explain SELECT org_uuid, project_uuid, collection_name, counter1, counter2, counter3 FROM collection_stats 
WHERE 
    org_uuid = UUID_TO_BIN('bb5c2330-1a85-11e9-8ad9-b728a2ed4173', 1) AND
    project_uuid = UUID_TO_BIN('faafad18-1a85-11e9-8a1d-b7281ece80f6', 1) AND
    date >= DATE_SUB(NOW(), INTERVAL 10 DAY)

解释说同样的。使用collection_usage_index 代替project_usage_index ..

对此的任何合乎逻辑的解释。我的表只有几行用于测试?可能是什么原因?

【问题讨论】:

    标签: indexing mysql-8.0


    【解决方案1】:

    您在WHERE 子句中使用了一个函数。据我所知,MySQL 不能使用函数和索引。
    您可以通过将date >= DATE_SUB(NOW(), INTERVAL 10 DAY) 更改为DATE >= $DATE 并检查来验证。

    【讨论】:

    • 最左边的前缀不应该只引用 WHERE 子句中的列吗?无论如何,从 SELECT 中删除列也没有任何区别。
    • @silviu:我更新了我的答案。我忘记了mysql和函数
    • 即使我从 where 子句中删除函数也没有变化
    • 很难知道优化器为什么选择某种方法。可能是project_uuiddate 的选择性不够,所以它也选择了collection_name 的索引。你也可以强制使用哪个索引
    猜你喜欢
    • 2015-07-12
    • 2013-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-22
    • 2018-10-05
    • 1970-01-01
    • 2018-10-12
    相关资源
    最近更新 更多