2016-09-29 25 views
1

如果您在一个表上使用非空列的计数,但没有任何where-parts,optimaizer只会返回该表中的行数。主键无效的mariadb优化

如果你要求UNIQE非空列的DISTINCT计数,如PRIMARY KEY,答案应该是相同的,但是这次mariadb做了insted的计算。

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

mariadb是否有没有使用这些优化的原因?有没有情况下,未经过滤的主键的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) 
); 

计数查询,1,基本合计

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上PRIMARY KEY和LEFT JOIN没有WHERE部分

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 | 
+------+-------------+--------------------+-------+---------------+---------+---------+----------------------------------+--------+-------------+ 
+0

您没有在表格定义中设置引擎。你在使用InnoDB还是MyISAM? –

+1

我的默认配置有:ENGINE = InnoDB –

+0

在这种情况下,您是否需要DISTINCT计算非空的唯一列?该结果与该列的正常计数有何不同? – Mjh

回答

2

“是否有理由让mariadb不使用这些优化?” - MySQL/MariaDB中有数十亿缺失的优化;这是缺少的。我们来看看历史。

MySQL在二十年前就开始作为一个精益和平均数据库引擎。它专注于大多数人需要的功能,同时尽量减少开销。这意味着很多罕见的优化不在早期版本中,并且只有在它们看起来足够重要的情况下才会随时添加。例如,可以使用PRIMARY KEY。它被定义为UNIQUE。它是BTree组织的。而且,对于InnoDB,它也被定义为集群。其他供应商允许各种组合聚类,非BTree索引等.MySQL认为对于“大多数”人来说这些限制是“足够好”的。

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

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个以上的查询是否真的需要它。 (我已经看到很多疑问)。我认为它的稀有性是为什么花了二十年来实现它。缺乏一个干净的解决方法是为什么它不需要再过十年。