【问题标题】:mariadb optimisation of primary key not working主键的mariadb优化不起作用
【发布时间】:2017-02-07 12:53:07
【问题描述】:

如果您对非空列使用计数,在一个表上,没有任何 where 部分,优化器只返回该表中的行数。

如果您要求对 UNIQE 非空列(如 PRIMARY KEY)进行 DISTINCT 计数,答案应该相同,但这次 mariadb 会进行 insted 计算。

如果您在其他表上留下了连接,但仍然没有 where-parts,则结果应该仍然是该表中的行数。

mariadb 是否有理由不使用 thou 优化?是否存在未过滤主键的 DISTINCT 计数可以给出任何其他结果而不是该表中的行数的情况?

案例:

CREATE TABLE products (
    our_article_id varchar(50) CHARACTER SET utf8 NOT NULL,
    ...,
    PRIMARY KEY(our_article_id)
);

CREATE TABLE product_article_id (
    article_id varchar(255) COLLATE utf8_bin NOT NULL,
    our_article_id varchar(50) CHARACTER SET utf8 NOT NULL,
    ...
    PRIMARY KEY(article_id),
    INDEX(our_article_id)
);

计数查询,第一次,基本计数

DESCRIBE SELECT COUNT(our_article_id) FROM products;         
+------+-------------+-------+------+---------------+------+---------+------+------+------------------------------+
| id   | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra                        |
+------+-------------+-------+------+---------------+------+---------+------+------+------------------------------+
|    1 | SIMPLE      | NULL  | NULL | NULL          | NULL | NULL    | NULL | NULL | Select tables optimized away |
+------+-------------+-------+------+---------------+------+---------+------+------+------------------------------+

主键上的第二个 DISTINCT

DESCRIBE SELECT COUNT(DISTINCT our_article_id) FROM products;
+------+-------------+----------+-------+---------------+---------+---------+------+--------+-------------+
| id   | select_type | table    | type  | possible_keys | key     | key_len | ref  | rows   | Extra       |
+------+-------------+----------+-------+---------------+---------+---------+------+--------+-------------+
|    1 | SIMPLE      | products | index | NULL          | PRIMARY | 152     | NULL | 225089 | Using index |
+------+-------------+----------+-------+---------------+---------+---------+------+--------+-------------+

第 3 个,主键上的 DISTINCT,以及没有 WHERE 部分的 LEFT JOIN

DESCRIBE SELECT COUNT(DISTINCT our_article_id) FROM products LEFT JOIN product_article_id USING (our_article_id);
+------+-------------+--------------------+-------+---------------+---------+---------+----------------------------------+--------+-------------+
| id   | select_type | table              | type  | possible_keys | key     | key_len | ref                              | rows   | Extra       |
+------+-------------+--------------------+-------+---------------+---------+---------+----------------------------------+--------+-------------+
|    1 | SIMPLE      | products           | index | NULL          | PRIMARY | 152     | NULL                             | 225089 | Using index |
|    1 | SIMPLE      | product_article_id | ref   | PRIMARY       | PRIMARY | 152     | testseek.products.our_article_id |  12579 | Using index |
+------+-------------+--------------------+-------+---------------+---------+---------+----------------------------------+--------+-------------+

【问题讨论】:

  • 您没有在表定义中设置引擎。您使用的是 InnoDB 还是 MyISAM?
  • 我的默认配置有:ENGINE=InnoDB
  • 在哪种情况下,您需要对非空唯一列进行 DISTINCT 计数?该结果与该列的常规计数有何不同?
  • 我认为@PugganSe 不是在问如何让他的查询更快,而是为什么 MariaDB / MySQL 查询规划器无法识别COUNT(DISTINCT pk) 总是与COUNT(*) 具有相同的结果。这样做的设计原因是什么?好问题!

标签: mysql mariadb


【解决方案1】:

“mariadb 是否有理由不使用 thou 优化?” -- MySQL/MariaDB 中缺少无数优化;那不见了。让我们看看历史。

MySQL 大约在 20 年前作为一个精简而平均的数据库引擎开始。它专注于大多数人需要的功能,同时最大限度地减少开销。这意味着许多罕见的优化不在早期版本中,只有在它们看起来足够重要时才会随着时间的推移而添加。

PRIMARY KEY 为例。它被定义为唯一。它是 BTree 组织的。而且,对于 InnoDB,它也被定义为 Clustered。其他供应商允许各种组合集群、非 BTree 索引等。MySQL 认为这些限制对于“大多数”人来说“足够好”。

多年来,“最糟糕”的遗漏已逐渐得到修复。交易可能是最大和最重要的。它于 2001 年问世(?),随着 8.0 的出现,MyISAM 在今年(2016 年)被删除。

4.1 (2002?) 看到子查询。在此之前,创建一个 tmp 表已经“足够好”了。现在 (8.0) 子查询被 CTE 提升了,它涵盖了一些 tmp 表和子查询都无法有效完成的事情。

在 MySQL 5.6 和 5.7 以及 MariaDB 10.x 中进行了大量优化;您可能没有使用过其中的几个。产品进入“收益递减”状态。如果它放慢优化器的速度来检查接下来的一千个极其罕见的优化,它将损害其“精益和卑鄙”的传统。

同时,像我这样的人花了很多时间说“MySQL/MariaDB 没有那个;这是解决方法”。在您的情况下,它是较短的 COUNT(*)。由于有一个干净的解决方法,您的建议可能还需要十年才能实施。可以向 bugs.mysql.com 或 mariadb.com 提交错误报告以提出优化建议。

另一个几乎从来不需要的情况是INDEX(a ASC, b DESC) 作为优化ORDER BY a ASC, b DESC 的一种方式。这是 8.0 的版本。但我怀疑是否有超过 5,000 个查询真的需要它。 (我看到了很多疑问。)我认为它的稀有性是为什么它花了二十年才实现的原因。没有一个干净的解决方法是它不需要再花十年的原因。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-24
    • 2021-05-29
    • 2018-07-22
    • 1970-01-01
    • 1970-01-01
    • 2017-09-16
    • 2021-04-06
    • 2017-11-26
    相关资源
    最近更新 更多