2016-09-29 36 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個以上的查詢是否真的需要它。 (我已經看到很多疑問)。我認爲它的稀有性是爲什麼花了二十年來實現它。缺乏一個乾淨的解決方法是爲什麼它不需要再過十年。