2017-08-28 3 views
0

Mit der gleichen Datenbankstruktur und Daten auf MySQL 5.6.34 (mein neuer Entwicklerserver) und MariaDB 10.2.8 (mein neuer Produktionsserver, wo ich dachte, dass ich den Code heute endlich bereitstellen würde - Seufz!), MySQL funktioniert und MariaDB ist nicht. Dies ist Code, der seit Jahren mit MySQL 5.0.95 funktioniert. Ich habe meine Abfrage auf das minimale Beispiel vereinfacht, das das Problem zeigt - es scheint, dass GROUP_CONCAT() und Unterabfragen nicht mischen. Hier ist die Abfrage:MariaDB: group_concat mit Unterabfrage fehlgeschlagen

SELECT person.PersonID, 
GROUP_CONCAT(CategoryID ORDER BY CategoryID SEPARATOR ',') AS categories 
FROM person LEFT JOIN percat ON person.PersonID=percat.PersonID 
WHERE person.PersonID IN (SELECT PersonID FROM action WHERE ActionTypeID=3) 
GROUP BY person.PersonID 

Und hier ist ein zusammengesetztes Bild von Screenshots, die die Struktur aller drei Tabellen beteiligt: ​​

enter image description here

auf MySQL, es funktioniert gut, wie es funktioniert hat jahrelang. Hier ist das Ergebnis und EXPLAIN:

MySQL 5.6.34

Und das ist das verrückt Ergebnis, das ich auf MariaDB erhalten:

enter image description here

Ich weiß nicht, das Innenleben des DB-Motors gut genug zu folgen EXPLAIN, aber ich nehme an, dass der Hinweis irgendwo dort ist. Ich fand das klingt verwandt, aber ich verstehe nicht wirklich, was sie darüber sagen, und was noch wichtiger ist, was ich dagegen tun sollte.

Antwort

1

Dies ist ein Fehler, anscheinend ist es nicht ganz derselbe wie der, den Sie gefunden haben (weil der Testfall aus dem erwähnten Fehlerbericht in 10.2.8 gut funktioniert, und Ihrs in der Tat nicht). Bitte zögern Sie nicht, eine neue unter MariaDB JIRA zu melden.

Inzwischen denke ich, sollten Sie durch

Einstellung um es in der Lage sein zu arbeiten
optimizer_switch=orderby_uses_equalities=off 

in Ihrer cnf-Datei. Es ist eine neu aktivierte Optimierung, offensichtlich nicht fehlerfrei.


UPDATE: Der Fehler jetzt als https://jira.mariadb.org/browse/MDEV-13694

+0

Ich kann nicht scheinen, wenn ausgeschaltet - anscheinend mache ich es falsch. In '/ etc/my.cnf', Sektion' [mysqld] ', fügte ich' optimizer_switch = orderby_uses_equalisities = off' hinzu (ich probierte es mit und ohne Hochkommas - ich sah Beispiele im Web von beiden) und startete mysqld neu (was hat auch seltsames Verhalten - es gibt meine ssh-Eingabeaufforderung nicht zurück, bis ich nach dem Warten auf^C drücke. Aber "SELECT @@ optimizer_switch \ G" sagt, dass "orderby_uses_equalities" noch an ist, und es gibt keine Änderung im Abfrageverhalten. – OsakaWebbie

+1

Der Abschnitt und die Linie sind in Ordnung. Überprüfen Sie zunächst, ob Ihr Server tatsächlich neu gestartet wird (z. B. durch Überprüfen von 'STATUS LIKE' Uptime'und/oder des Fehlerprotokolls). Es hört sich so an, als ob der Server nicht wirklich herunterfährt, dann neu startet und um das Datenverzeichnis kämpft , z.B für die Sperre über Aria-Steuerdatei oder dergleichen. Wenn der Server tatsächlich neu gestartet wird, besteht der andere mögliche Grund darin, dass diese CNF-Datei nicht von Ihrer Installation verwendet wird. Sie können etwas nach dem optimizer_switch, z. 'lock_wait_timeout = 42' (oder was auch immer Sie erkennen würden), und sehen Sie, ob es abgeholt wird. – elenst

+0

Yup, das war es - es hatte nicht wirklich neu gestartet (ich habe den Befehl falsch gemacht). Ihr Workaround funktioniert wie ein Zauber! Wenn ich mehr Zeit habe, werde ich daran arbeiten, meinen Code zu vereinfachen, aber im Moment kann ich dank Ihnen den neuen Server hochfahren. – OsakaWebbie

0

Umgehung berichtet Dies wird nicht beantworten, warum es einen Unterschied gibt, aber man sollte DISTINCT zum GROUP_CONCAT hinzuzufügen.

Das "Warum" Wahrscheinlich ist die Antwort in den Optimizers sehr tief verwurzelt. Seit 5.0 gab es viele Änderungen. 5.6 hatte viel neuen Code; zur gleichen Zeit gab MariaDB in 10.0 ab. Bei dieser Verzweigung divergierten die Optimierer erheblich. 10.2 hat sich weiter vorwärts bewegt, aber nicht unbedingt in diese Art der Abfrage optimieren.

Verbesserte Abfrage Es gibt mehrere Dinge, die mit der Abfrage erledigt werden könnten. Einige werden wahrscheinlich es schneller:

SELECT p.PersonID, 
     (SELECT GROUP_CONCAT(pc.CategoryID 
           ORDER BY CategoryID SEPARATOR ',') 
      FROM percat 
      WHERE PersonID = p.PersonID 
     ) AS categories 
    FROM person 
    JOIN action AS a ON p.PersonID = a.PersonID 
    WHERE ActionTypeID = 3 
    GROUP BY p.PersonID 

Transforming der LEFT JOIN wird wahrscheinlich die Last auf GROUP BY verringern. Möglicherweise kann die GROUP BY entfernt werden.

Wegen PRIMARY KEY(PersonID, CategoryID) sollte DISTINCT nicht benötigt werden.

Benötigter Index Dieser "Deckungsindex" würde die Dinge mehr beschleunigen: INDEX(ActionTypeID, PersonID).

+0

Das Hinzufügen von DISTINCT löschte nur die wiederholten CategoryIDs - es hatte keine Auswirkung auf das Hauptproblem: Ich bekomme immer noch nur eine Person, wenn es ein Vielfaches geben sollte. Wenn Sie Ihre Idee optimieren möchten, indem Sie die Unterabfrage zu einem Join ändern, sollten Sie beachten, dass die Abfrage, die ich hier geteilt habe, extrem vereinfacht ist. In meiner realen Anwendung kann der Benutzer eine Vielzahl von Suchkriterien kombinieren und programmgesteuert machen Wählen Sie eine funktionierende Abfrage. Ich war nicht in der Lage, einen Weg zu finden, dies ohne Unterabfragen zu tun. – OsakaWebbie

+0

'GROUP BY PersonID' _causes_ gibt es nur eine Zeile pro Person. Ich denke, ich weiß nicht, was du willst. Und Ihre Beispielausgabe hat nur eine Zeile pro Person. Mock-up die Ausgabe, die Sie wollen. –

+0

Es gibt vier Personen, die dem WHERE entsprechen, daher sollten vier Zeilen zurückgegeben werden. Die korrekte Ausgabe ist im Screenshot "On MySQL ..." zu sehen. Ich weiß nicht, warum die ersten drei Leute nicht zurückkommen, aber das ist das Hauptproblem. – OsakaWebbie