2016-09-29 5 views
1

Wenn Sie eine Zählung für eine Nicht-Null-Spalte in einer Tabelle ohne Where-Teile verwenden, gibt der Optimaizer nur die Anzahl der Zeilen in dieser Tabelle zurück.Mariadb-Optimierung des Primärschlüssels funktioniert nicht

Wenn Sie nach einer DISTINCT-Zählung auf einer UNIQE-Nicht-Null-Spalte, wie dem PRIMARY KEY, fragen, sollten die Antworten identisch sein, aber dieses Mal führt Mariadb die Berechnungen aus.

Und wenn Sie Join auf anderen Tabellen verlassen haben und noch keine Where-Teile, sollten die Ergebnisse immer noch die Anzahl der Zeilen in dieser Tabelle sein.

Gibt es einen Grund dafür, dass Mariadb keine Tausender-Optimierungen verwendet? Gibt es einen Fall, wenn die DISTINCT-Zählung eines ungefilterten Primärschlüssels irgendein anderes Ergebnis als die Anzahl der Zeilen in dieser Tabelle ergibt?

Fall:

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) 
); 

Count-Abfragen, 1., Grundzahl

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

2. DISTINCT auf Primärschlüssel

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 auf PRIMARY KEY und eine LEFT JOIN ohne WO-Teile

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

Sie legen in der Tabellendefinition keine Engine fest. Verwenden Sie InnoDB oder MyISAM? –

+1

meine Standardkonfiguration habe: ENGINE = InnoDB –

+0

In welchem ​​Fall würden Sie in einer Situation sein, in der Sie DISTINCT Count auf einer nicht null eindeutigen Spalte benötigen? Wie würde dieses Ergebnis von einer normalen Anzahl in dieser Spalte abweichen? – Mjh

Antwort

2

"Gibt es einen Grund für Mariadb nicht mit Tsots Optimierungen?" - Es gibt eine Zillion fehlender Optimierungen in MySQL/MariaDB; das fehlt. Schauen wir uns die Geschichte an.

MySQL begann vor etwa 2 Jahrzehnten als eine schlanke und gemeine Datenbank-Engine. Es konzentrierte sich auf Funktionen, die die meisten Menschen benötigten, und minimierte den Overhead. Dies bedeutete, dass viele seltene Optimierungen nicht in den frühen Versionen waren, und nur im Laufe der Zeit hinzugefügt werden, wenn sie wichtig genug erscheinen.

Nehmen Sie zum Beispiel die PRIMARY KEY. Es ist als einzigartig definiert. Es ist BTree organisiert. Und mit InnoDB wird es auch als Cluster definiert. Andere Anbieter erlauben verschiedene Kombinationen von Clustering, Nicht-BTree-Indizierung usw. MySQL entschied, dass die Beschränkungen für "die meisten" Leute "gut genug" waren.

Im Laufe der Jahre wurden die "schlimmsten" Auslassungen allmählich behoben. Transaktionen sind wahrscheinlich die größten und wichtigsten. Es kam im Jahr 2001 (?), Und MyISAM wird in diesem Jahr (2016) mit dem Aufkommen von 8.0 entfernt.

4.1 (2002?) Sah Unterabfragen. Vorher war das Erstellen einer TMP-Tabelle "gut genug". Jetzt werden (8.0) Unterabfragen von CTEs um eins erhöht, was ein paar Dinge abdeckt, die weder tmp-Tabellen noch Unterabfragen effizient erledigen können.

Es gab eine große Anzahl von Optimierungen in MySQL 5.6 und 5.7 und MariaDB 10.x; Sie haben wahrscheinlich nicht mehr als ein paar von ihnen verwendet. Das Produkt ist in "abnehmenden Renditen". Es würde sein "mageres und mittleres" Erbe beschädigen, wenn es den Optimierer verlangsamt, um nach den nächsten tausend extrem seltenen Optimierungen zu suchen.

In der Zwischenzeit verbringen Leute wie ich eine Menge Zeit damit, zu sagen: "MySQL/MariaDB hat das nicht; hier ist die Problemumgehung". Es ist die kürzere COUNT(*) in Ihrem Fall. Da es einen sauberen Workaround gibt, kann es noch ein Jahrzehnt dauern, bis Ihre Vorschläge implementiert werden. Es ist in Ordnung, einen Fehlerbericht mit bugs.mysql.com oder mariab.com einzureichen, um die Optimierungen vorzuschlagen.

Ein weiterer, fast nie benötigter Fall ist INDEX(a ASC, b DESC) als eine Art der Optimierung ORDER BY a ASC, b DESC. Das kommt mit 8.0. Aber ich bezweifle, dass mehr als eine Abfrage in 5.000 es wirklich braucht. (Ich habe viele Fragen gesehen.) Ich schlage vor, dass es selten ist, warum es zwei Jahrzehnte dauerte, um es umzusetzen. Das Fehlen eines sauberen Workarounds hat dazu geführt, dass es nicht ein weiteres Jahrzehnt dauerte.

Verwandte Themen