2016-05-25 9 views
4

vor kurzem komme ich mit einigen MySQL-Performance-Probleme auf, hier ist die Abfrage:Join-Abfrage Optimierung

select 
     assoc.id     as id, 
     parentNode.id    as parentNodeId, 
     parentNode.version   as parentNodeVersion, 
     parentStore.protocol  as parentNodeProtocol, 
     parentStore.identifier  as parentNodeIdentifier, 
     parentNode.uuid    as parentNodeUuid, 
     childNode.id    as childNodeId, 
     childNode.version   as childNodeVersion, 
     childStore.protocol   as childNodeProtocol, 
     childStore.identifier  as childNodeIdentifier, 
     childNode.uuid    as childNodeUuid, 
     assoc.type_qname_id   as type_qname_id, 
     assoc.child_node_name_crc as child_node_name_crc, 
     assoc.child_node_name  as child_node_name, 
     assoc.qname_ns_id   as qname_ns_id, 
     assoc.qname_localname  as qname_localname, 
     assoc.is_primary   as is_primary, 
     assoc.assoc_index   as assoc_index 


    from 
     alf_child_assoc assoc 
     join alf_node parentNode on (parentNode.id = assoc.parent_node_id) 
     join alf_store parentStore on (parentStore.id = parentNode.store_id) 
     join alf_node childNode on (childNode.id = assoc.child_node_id) 
     join alf_store childStore on (childStore.id = childNode.store_id) 

    where 
     parentNode.id = 837 
    order by 
     assoc.assoc_index ASC, 
     assoc.id ASC; 

Das Problem ist, dass die Abfrage zu lange gedauert hat Sortier- und Senden Ergebnismenge. Jede Hilfe ist willkommen, danke im voraus

einige Zählung info:

mysql> select count(id) from alf_child_assoc; 
+-----------+ 
| count(id) | 
+-----------+ 
| 7208882 | 
+-----------+ 
1 row in set (12.51 sec) 

mysql> select count(id) from alf_node; 
+-----------+ 
| count(id) | 
+-----------+ 
| 3986059 | 
+-----------+ 
1 row in set (1.68 sec) 

mysql> select count(id) from alf_store; 
+-----------+ 
| count(id) | 
+-----------+ 
|   6 | 
+-----------+ 
1 row in set (0.00 sec) 

Dies ist die explain Ausgabe:

+----+-------------+-------------+--------+---------------------------------------------------------------------+----------------+---------+--------------------------+--------+----------------+ 
| id | select_type | table  | type | possible_keys              | key   | key_len | ref      | rows | Extra   | 
+----+-------------+-------------+--------+---------------------------------------------------------------------+----------------+---------+--------------------------+--------+----------------+ 
| 1 | SIMPLE  | parentNode | const | PRIMARY,store_id,fk_alf_node_store,will_store_node_idx    | PRIMARY  | 8  | const     |  1 | Using filesort | 
| 1 | SIMPLE  | parentStore | const | PRIMARY                | PRIMARY  | 8  | const     |  1 |    | 
| 1 | SIMPLE  | assoc  | ref | parent_node_id,fk_alf_cass_pnode,fk_alf_cass_cnode,idx_alf_cass_pri | parent_node_id | 8  | const     | 275218 | Using where | 
| 1 | SIMPLE  | childNode | eq_ref | PRIMARY,store_id,fk_alf_node_store,will_store_node_idx    | PRIMARY  | 8  | repo.assoc.child_node_id |  1 |    | 
| 1 | SIMPLE  | childStore | eq_ref | PRIMARY                | PRIMARY  | 8  | repo.childNode.store_id |  1 |    | 
+----+-------------+-------------+--------+---------------------------------------------------------------------+----------------+---------+--------------------------+--------+----------------+ 
5 rows in set (0.00 sec) 

Nachfolgend finden Sie einige tabellenbezogenen Informationen:

mysql> desc alf_child_assoc; 
+---------------------+--------------+------+-----+---------+----------------+ 
| Field    | Type   | Null | Key | Default | Extra   | 
+---------------------+--------------+------+-----+---------+----------------+ 
| id     | bigint(20) | NO | PRI | NULL | auto_increment | 
| version    | bigint(20) | NO |  | NULL |    | 
| parent_node_id  | bigint(20) | NO | MUL | NULL |    | 
| type_qname_id  | bigint(20) | NO | MUL | NULL |    | 
| child_node_name_crc | bigint(20) | NO |  | NULL |    | 
| child_node_name  | varchar(50) | NO |  | NULL |    | 
| child_node_id  | bigint(20) | NO | MUL | NULL |    | 
| qname_ns_id   | bigint(20) | NO | MUL | NULL |    | 
| qname_localname  | varchar(255) | NO |  | NULL |    | 
| qname_crc   | bigint(20) | NO | MUL | NULL |    | 
| is_primary   | bit(1)  | YES |  | NULL |    | 
| assoc_index   | int(11)  | YES | MUL | NULL |    | 
+---------------------+--------------+------+-----+---------+----------------+ 
12 rows in set (0.00 sec) 

mysql> desc alf_node; 
+----------------+--------------+------+-----+---------+----------------+ 
| Field   | Type   | Null | Key | Default | Extra   | 
+----------------+--------------+------+-----+---------+----------------+ 
| id    | bigint(20) | NO | PRI | NULL | auto_increment | 
| version  | bigint(20) | NO |  | NULL |    | 
| store_id  | bigint(20) | NO | MUL | NULL |    | 
| uuid   | varchar(36) | NO |  | NULL |    | 
| transaction_id | bigint(20) | NO | MUL | NULL |    | 
| node_deleted | bit(1)  | NO | MUL | NULL |    | 
| type_qname_id | bigint(20) | NO | MUL | NULL |    | 
| locale_id  | bigint(20) | NO | MUL | NULL |    | 
| acl_id   | bigint(20) | YES | MUL | NULL |    | 
| audit_creator | varchar(255) | YES |  | NULL |    | 
| audit_created | varchar(30) | YES |  | NULL |    | 
| audit_modifier | varchar(255) | YES |  | NULL |    | 
| audit_modified | varchar(30) | YES |  | NULL |    | 
| audit_accessed | varchar(30) | YES |  | NULL |    | 
+----------------+--------------+------+-----+---------+----------------+ 
14 rows in set (0.00 sec) 

mysql> desc alf_store; 
+--------------+--------------+------+-----+---------+----------------+ 
| Field  | Type   | Null | Key | Default | Extra   | 
+--------------+--------------+------+-----+---------+----------------+ 
| id   | bigint(20) | NO | PRI | NULL | auto_increment | 
| version  | bigint(20) | NO |  | NULL |    | 
| protocol  | varchar(50) | NO | MUL | NULL |    | 
| identifier | varchar(100) | NO |  | NULL |    | 
| root_node_id | bigint(20) | YES | MUL | NULL |    | 
+--------------+--------------+------+-----+---------+----------------+ 
5 rows in set (0.00 sec) 

mysql> 
mysql> show index from alf_node; 
+----------+------------+----------------------+--------------+----------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 
| Table | Non_unique | Key_name    | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | 
+----------+------------+----------------------+--------------+----------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 
| alf_node |   0 | PRIMARY    |   1 | id    | A   |  3890448 |  NULL | NULL |  | BTREE  |   |    | 
| alf_node |   0 | store_id    |   1 | store_id  | A   |   18 |  NULL | NULL |  | BTREE  |   |    | 
| alf_node |   0 | store_id    |   2 | uuid   | A   |  3890448 |  NULL | NULL |  | BTREE  |   |    | 
| alf_node |   1 | idx_alf_node_del  |   1 | node_deleted | A   |   18 |  NULL | NULL |  | BTREE  |   |    | 
| alf_node |   1 | idx_alf_node_txn_del |   1 | transaction_id | A   |  3890448 |  NULL | NULL |  | BTREE  |   |    | 
| alf_node |   1 | idx_alf_node_txn_del |   2 | node_deleted | A   |  3890448 |  NULL | NULL |  | BTREE  |   |    | 
| alf_node |   1 | fk_alf_node_acl  |   1 | acl_id   | A   |  3890448 |  NULL | NULL | YES | BTREE  |   |    | 
| alf_node |   1 | fk_alf_node_txn  |   1 | transaction_id | A   |  3890448 |  NULL | NULL |  | BTREE  |   |    | 
| alf_node |   1 | fk_alf_node_store |   1 | store_id  | A   |   18 |  NULL | NULL |  | BTREE  |   |    | 
| alf_node |   1 | fk_alf_node_tqn  |   1 | type_qname_id | A   |   18 |  NULL | NULL |  | BTREE  |   |    | 
| alf_node |   1 | fk_alf_node_loc  |   1 | locale_id  | A   |   18 |  NULL | NULL |  | BTREE  |   |    | 
| alf_node |   1 | will_store_node_idx |   1 | id    | A   |  3890448 |  NULL | NULL |  | BTREE  |   |    | 
| alf_node |   1 | will_store_node_idx |   2 | store_id  | A   |  3890448 |  NULL | NULL |  | BTREE  |   |    | 
+----------+------------+----------------------+--------------+----------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 
13 rows in set (0.01 sec) 

mysql> show index from alf_store; 
+-----------+------------+-------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 
| Table  | Non_unique | Key_name   | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | 
+-----------+------------+-------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 
| alf_store |   0 | PRIMARY   |   1 | id   | A   |   6 |  NULL | NULL |  | BTREE  |   |    | 
| alf_store |   0 | protocol   |   1 | protocol  | A   |   6 |  NULL | NULL |  | BTREE  |   |    | 
| alf_store |   0 | protocol   |   2 | identifier | A   |   6 |  NULL | NULL |  | BTREE  |   |    | 
| alf_store |   1 | fk_alf_store_root |   1 | root_node_id | A   |   6 |  NULL | NULL | YES | BTREE  |   |    | 
+-----------+------------+-------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 
4 rows in set (0.00 sec) 

mysql> show index from alf_child_assoc; 
+-----------------+------------+--------------------+--------------+---------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 
| Table   | Non_unique | Key_name   | Seq_in_index | Column_name   | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | 
+-----------------+------------+--------------------+--------------+---------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 
| alf_child_assoc |   0 | PRIMARY   |   1 | id     | A   |  6956126 |  NULL | NULL |  | BTREE  |   |    | 
| alf_child_assoc |   0 | parent_node_id  |   1 | parent_node_id  | A   |  632375 |  NULL | NULL |  | BTREE  |   |    | 
| alf_child_assoc |   0 | parent_node_id  |   2 | type_qname_id  | A   |  632375 |  NULL | NULL |  | BTREE  |   |    | 
| alf_child_assoc |   0 | parent_node_id  |   3 | child_node_name_crc | A   |  6956126 |  NULL | NULL |  | BTREE  |   |    | 
| alf_child_assoc |   0 | parent_node_id  |   4 | child_node_name  | A   |  6956126 |  NULL | NULL |  | BTREE  |   |    | 
| alf_child_assoc |   1 | fk_alf_cass_pnode |   1 | parent_node_id  | A   |  695612 |  NULL | NULL |  | BTREE  |   |    | 
| alf_child_assoc |   1 | fk_alf_cass_cnode |   1 | child_node_id  | A   |  6956126 |  NULL | NULL |  | BTREE  |   |    | 
| alf_child_assoc |   1 | fk_alf_cass_tqn |   1 | type_qname_id  | A   |   16 |  NULL | NULL |  | BTREE  |   |    | 
| alf_child_assoc |   1 | fk_alf_cass_qnns |   1 | qname_ns_id   | A   |   16 |  NULL | NULL |  | BTREE  |   |    | 
| alf_child_assoc |   1 | idx_alf_cass_qncrc |   1 | qname_crc   | A   |  3478063 |  NULL | NULL |  | BTREE  |   |    | 
| alf_child_assoc |   1 | idx_alf_cass_qncrc |   2 | type_qname_id  | A   |  6956126 |  NULL | NULL |  | BTREE  |   |    | 
| alf_child_assoc |   1 | idx_alf_cass_qncrc |   3 | parent_node_id  | A   |  6956126 |  NULL | NULL |  | BTREE  |   |    | 
| alf_child_assoc |   1 | idx_alf_cass_pri |   1 | parent_node_id  | A   |  1159354 |  NULL | NULL |  | BTREE  |   |    | 
| alf_child_assoc |   1 | idx_alf_cass_pri |   2 | is_primary   | A   |  1159354 |  NULL | NULL | YES | BTREE  |   |    | 
| alf_child_assoc |   1 | idx_alf_cass_pri |   3 | child_node_id  | A   |  6956126 |  NULL | NULL |  | BTREE  |   |    | 
| alf_child_assoc |   1 | will_order_idx  |   1 | assoc_index   | A   |   16 |  NULL | NULL | YES | BTREE  |   |    | 
| alf_child_assoc |   1 | will_order_idx  |   2 | id     | A   |  6956126 |  NULL | NULL |  | BTREE  |   |    | 
+-----------------+------------+--------------------+--------------+---------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 
17 rows in set (0.16 sec) 

nach lesen @ Solarflare's Antwort, habe ich es ausprobiert, jetzt die Abfrage wird:

SELECT STRAIGHT_JOIN 
    assoc.id AS id, 
    parentNode.id AS parentNodeId, 
    parentNode.version AS parentNodeVersion, 
    parentStore.protocol AS parentNodeProtocol, 
    parentStore.identifier AS parentNodeIdentifier, 
    parentNode.uuid AS parentNodeUuid, 
    childNode.id AS childNodeId, 
    childNode.version AS childNodeVersion, 
    childStore.protocol AS childNodeProtocol, 
    childStore.identifier AS childNodeIdentifier, 
    childNode.uuid AS childNodeUuid, 
    assoc.type_qname_id AS type_qname_id, 
    assoc.child_node_name_crc AS child_node_name_crc, 
    assoc.child_node_name AS child_node_name, 
    assoc.qname_ns_id AS qname_ns_id, 
    assoc.qname_localname AS qname_localname, 
    assoc.is_primary AS is_primary, 
    assoc.assoc_index AS assoc_index 
FROM 
    alf_child_assoc assoc FORCE INDEX (will_subq_idx) 
     JOIN 
    alf_node parentNode ON (parentNode.id = assoc.parent_node_id) 
     JOIN 
    alf_node childNode ON (childNode.id = assoc.child_node_id) 
     JOIN 
    alf_store parentStore ON (parentStore.id = parentNode.store_id) 
     JOIN 
    alf_store childStore ON (childStore.id = childNode.store_id) 
WHERE 
    parentNode.id = 550 
ORDER BY assoc.assoc_index ASC , assoc.id ASC; 

und die Shows erklären:

+----+-------------+-------------+------------+--------+-----------------------------------------------------------------------+---------------+---------+--------------------------+--------+----------+---------------------------------------+ 
| id | select_type | table  | partitions | type | possible_keys               | key   | key_len | ref      | rows | filtered | Extra         | 
+----+-------------+-------------+------------+--------+-----------------------------------------------------------------------+---------------+---------+--------------------------+--------+----------+---------------------------------------+ 
| 1 | SIMPLE  | assoc  | NULL  | ref | will_subq_idx               | will_subq_idx | 8  | const     | 303104 | 100.00 | Using index condition; Using filesort | 
| 1 | SIMPLE  | parentNode | NULL  | const | PRIMARY,store_id,fk_alf_node_store,will_store_node_idx,will_store_idx | PRIMARY  | 8  | const     |  1 | 100.00 | NULL         | 
| 1 | SIMPLE  | childNode | NULL  | eq_ref | PRIMARY,store_id,fk_alf_node_store,will_store_node_idx,will_store_idx | PRIMARY  | 8  | repo.assoc.child_node_id |  1 | 100.00 | NULL         | 
| 1 | SIMPLE  | parentStore | NULL  | eq_ref | PRIMARY,will_store_idx            | PRIMARY  | 8  | repo.parentNode.store_id |  1 | 100.00 | NULL         | 
| 1 | SIMPLE  | childStore | NULL  | eq_ref | PRIMARY,will_store_idx            | PRIMARY  | 8  | repo.childNode.store_id |  1 | 100.00 | NULL         | 
+----+-------------+-------------+------------+--------+-----------------------------------------------------------------------+---------------+---------+--------------------------+--------+----------+---------------------------------------+ 
5 rows in set, 1 warning (0.03 sec) 

dies ist die Abfrage-Plan von MySQL Workbench zeigte:

enter image description here

Dank für euch, Sie‘ das ist großartig!

+0

Ich habe versucht, die sortierpufferbezogenen Variablen zu optimieren; Hinzufügen eines Indexes mit den ORDER BY-Schlüsseln, aber keiner half. Die Ergebnismenge beträgt etwa 140.000 Datensätze, 32 MByte. – oxnz

Antwort

0

Sie können die einzelnen großen Abfrage auf mehrere Teile in temporären Tabellen aufgeteilt und dann das Endergebnis Satz .. fusionieren sieht

with tmp1 as (
    SELECT table1.column1, table2.column2... 
    FROM table1 JOIN table2 
    ON table1.common_field = table2.common_field), 

tmp2 as (
    SELECT table3.column1, table4.column2... 
    FROM table3 JOIN table4 
    ON table3.common_field = table4.common_field) 

select a.column1, a.column2, b.column1, b.column2 .. from tmp1 a join tmp2 b on a.Something = b.Something; 
0

Insgesamt ok. Ich würde vorschlagen, die folgende Index

table   index 
alf_child_assoc (parent_node_id, child_node_id, assoc_index, id) 

zweiten Zugabe, da Ihre Anfrage hinken ist, würde ich das Stichwort „STRAIGHT_JOIN“ versuchen und die explizite Reihenfolge der Wechsel von/join Kriterien der folgenden

SELECT STRAIGHT_JOIN 
     ... all your fields... 
    from 
     alf_node parentNode 
     join alf_store parentStore 
      on parentNode.store_id = parentStore.id 
     join alf_child_assoc assoc 
      on parentNode.id = assoc.parent_node_id 
      join alf_node childNode 
       on assoc.child_node_id = childNode.id 
       join alf_store childStore 
        on childNode.store_id = childStore.id 
    ... rest of query where/order by... 

SOMETIMES (nicht alle), sagt der STRAIGHT_JOIN MySql, um die Abfrage in der genauen Reihenfolge auszuführen, wie Sie die Tabellen aufgelistet haben. Der Rest Ihrer Indizes scheint in Ordnung zu sein (mit der einen Ausnahme, die ich denke, sollte hinzugefügt werden). Indem Sie den ParentNode-Alias ​​an die erste Position und in die WHERE-Klausel setzen, hilft STRAIGHT_JOIN MIGHT der Engine beim Erraten, welche Tabelle in die erste Position gestellt werden soll und so weiter.

Ich habe dies in einem anderen System verwendet, das staatliche Zuschüsse/Verträge Millionen von Datensätzen abfragt und die Haupttabelle mit über 20 Nachschlagetabellen verbindet. Abfrage nach 24 Stunden gehängt. Hinzufügen von STRAIGHT_JOIN, Abfrage in weniger als 2 Stunden abgeschlossen. Ja, wir haben viele Daten erwartet.

0

Der relevante Schlüssel, den Sie hier brauchen, ist alf_store(parent_node_id, child_node_id). Sie haben den Index idx_alf_cass_pri mit (parent_node_id, is_primary, child_node_id), der nicht verwendet wird.

Bitte versuchen Sie die folgenden Schritte, um Ihre Abfrage zu optimieren:

Erstellen Sie den Index alf_store(parent_node_id, child_node_id).

Ein zweiter Index, den Sie später brauchen könnte, ist alf_node(id, store_id, version, uuid) (Sie die Reihenfolge der version und uuid ändern können, auf anderen Anwendungsfällen abhängig), so ist es jetzt auch hinzufügen.

Execute/Erklären Sie die folgende zentrale Abfrage

select parentNode.id as parentNodeID, childnode.id as childNodeID, 
     assoc.id as assocID 
from alf_node as parentNode 
join alf_child_assoc as assoc on (parentNode.id = assoc.parent_node_id) 
join alf_node childNode on (childNode.id = assoc.child_node_id) 
where parentNode.id = 837; 

Dies wird die minimale Laufzeit der Anfrage bestimmen. Basierend auf den Tabellengrößen und den gegebenen Timings, sollte es ungefähr 0,5 Sekunden dauern, zumindest wenn Sie es ein zweites Mal ausführen, um alles gepuffert zu haben (und natürlich die Zeit, die zum Zurückgeben der Zeilen benötigt wird, also select count(*) from alf_store as ... zum Testen dieser Zeit).

Der nächste Schritt besteht darin, dies mit den Speichertabellen zu verbinden und die verbleibenden Spalten aus der Tabelle abzurufen. Es gibt einige mögliche Methoden, die sollten, in einer perfekten Datenbank, die gleiche durchführen, aber in Wirklichkeit hängt ein wenig auf dem Tisch Inhalt, können Sie es testen müssen:

select assoc.id as id, 
     ... 
from (
    select parentNode.id as parentNodeID, childnode.id as childNodeID, 
      assoc.id as assocID 
    from alf_node as parentNode 
    join alf_child_assoc as assoc on (parentNode.id = assoc.parent_node_id) 
    join alf_node childNode on (childNode.id = assoc.child_node_id) 
    where parentNode.id = 837 
) as subquery 
join alf_child_assoc assoc on (assoc.id = subquery.assocID) 
join alf_node parentNode on (parentNode.id = subquery.parentnodeID) 
-- join alf_store parentStore on (parentStore.id = parentNode.store_id) 
join alf_node childNode on (childNode.id = subquery.childNodeID) 
-- join alf_store childStore on (childStore.id = childNode.store_id) 
order by 
    assoc.assoc_index ASC, 
    assoc.id ASC; 

In einem ersten Schritt lassen sich die 6 Reihen von Geschäftsinformationen - sie sollten keine Auswirkungen haben, aber könnten etwas vermasseln, also teste ohne sie zuerst; Wenn sie eine Auswirkung haben, gibt es Möglichkeiten, mysql zu zwingen, sie korrekt zu optimieren.

Der Deckungsindex alf_node(id, store_id, version, uuid) von vorher sollte Ihnen ein besseres Ergebnis auf der äußeren Verbindung geben, also fügen Sie es jetzt hinzu, wenn Sie noch nicht haben. Sie könnten andere abdeckende Indizes hinzufügen, aber der einzige nützliche andere Index wäre assoc, und das würde im Grunde alle Daten in der Tabelle bedeuten, und das könnte übertrieben sein.

Überprüfen Sie immer, ob die innere Unterabfrage immer noch dieselbe ist, besonders wenn sie an einem Punkt langsamer wird. Möglicherweise müssen Sie mysql zwingen, den richtigen Index zu verwenden, da es möglicherweise eine andere Optimierung erfordert (die zwar korrekt sein kann, aber falsch sein kann).

Es kann immer noch ein paar Sekunden dauern, um alle Nachschlagevorgänge durchzuführen, abhängig von Ihren Daten, Datenfragmentierung und einigen anderen Dingen.

Eine andere Möglichkeit wäre, nach und nach die äußeren Informationen an die innere Abfrage hinzuzufügen, so dass Sie einige der zusätzlichen überspringen schließt sich, dass ich auf der äußeren Abfrage wieder eingeführt:

select assoc.id as id, 
     ... 
     subquery.ParentNodeVersion, 
     subquery.ParentNodeUuid, 
     ... 
from (
    select parentNode.id as parentNodeID, childnode.id as childNodeID, 
      assoc.id as assocID, 
      parentNode.store_Id as ParentNodeStoreID, 
      parentNode.Version as ParentNodeVersion, 
      parentNode.uuid as ParentNodeUuid, 
      childNode.store_Id as ChildNodeStoreID, 
      childNode.Version as ChildNodeVersion, 
      childNode.uuid as ChildNodeUuid 
    from alf_node as parentNode 
    join alf_child_assoc as assoc on (parentNode.id = assoc.parent_node_id) 
    join alf_node childNode on (childNode.id = assoc.child_node_id) 
    where parentNode.id = 837 
) as subquery 
join alf_child_assoc assoc on (assoc.id = subquery.assocID) 
-- join alf_store parentStore on (parentStore.id = subquery.parentNodeStoreId) 
-- join alf_store childStore on (childStore.id = subquery.ChildNodeStoreID) 
order by 
    assoc.assoc_index ASC, 
    assoc.id ASC; 

Wieder mit einer Version starten, ohne speichert, und es kann besser sein, sie auch in der Unterabfrage hinzuzufügen.

Dies ist manchmal ein wenig Versuch und Irrtum, die Unterabfrage und/oder abdeckende Indizes zu optimieren, Sie könnten testen, überprüfen erklärt und erneut fragen, wenn Sie einen spezifischen Engpass bekommen.

Die dritte Option besteht darin, Ihre ursprüngliche Abfrage zu verwenden (dies würde bedeuten, dass nach und nach alle Spalten in die Unterabfrage eingefügt werden, sodass sie keine Unterabfrage mehr ist).

Alle Optionen sollten tatsächlich die gleiche Leistung mit diesen Indizes haben, weil sie das gleiche ausdrücken, aber leider ist das nicht immer die Realität, denn es hängt von richtigen Statistiken ab, und diese sind nicht perfekt, also müssen Sie teste es ein bisschen.

Aber wie gesagt: der Hauptpunkt ist, den richtigen Index auf dem zentralen 3-Tabellen-Join zu verwenden, der andere Punkt besteht darin, zu versuchen, Tabellen-Lookups durch z. Indizes abdecken oder die Abfrage neu anordnen.

+0

danke für Ihre Antwort, ich habe es ausprobiert, und die Unterabfrage wird ausgeführt, wie Sie erwartet, es dauert etwa 0,3 Sekunden, aber die Unterabfrage hat eine sehr große Ergebnismenge, und das ist das Profil: – oxnz

+0

Ausführung | 0.000004 | | Daten senden | 0.266772 | | init | 0.000128 | | Tmp-Tabelle erstellen | 0.000040 | | Ausführen | 0.000003 | | In tmp-Tabelle kopieren | 0.460175 | | Konvertieren von HEAP in MyISAM | 0.155992 | | Kopieren in die Tabelle tmp auf der Festplatte | 0.583183 | | Sortierergebnis | 0.180695 | | Daten senden | 0.687862 | | Ende | 0.000014 | | tmp Tabelle entfernen | 0.058919 | – oxnz

+0

@oxnz Ich bin nicht sicher, ob das ein "nun, alles ist gut und schnell jetzt", "der erste Schritt ist in Ordnung, ich werde den Rest als nächstes versuchen" oder "Ich bekomme immer noch eine Menge Ergebnisse" -Kommentar . Wenn Ihre Anfrage 140k Datensätze enthält, dauert es eine Weile, bis sie gesendet werden. Es gibt wenig, was Sie tun können, wenn Sie alle benötigen. Oder suchen Sie nur nach einer Möglichkeit, nur einige von ihnen an Ihren Kunden zu senden? Dann können Sie einfach "Limit 20" oder "Limit 20 100" zum Ende hinzufügen, um nur einige der Ergebnisse zu senden. – Solarflare