0

Ich habe die folgende Abfrage mit einer Unterabfrage und Selbst verbinden:Optimierung der Abfrage mit Abdeckung Indizes

SELECT bucket.patient_sid AS sid 
FROM 
(SELECT clinical_data.patient_sid, 
     clinical_data.lft, 
     clinical_data.rgt 
FROM clinical_data INNER JOIN 
(SELECT clinical_data.patient_sid, 
     clinical_data.lft, 
     clinical_data.rgt, 
     clinical_data.attribute_id 
FROM clinical_data 
WHERE clinical_data.attribute_id = '33' AND clinical_data.string_value = '2160-0') AS attribute 
ON clinical_data.patient_sid = attribute.patient_sid 
    AND clinical_data.lft >= attribute.lft 
    AND clinical_data.rgt <= attribute.rgt 
WHERE clinical_data.attribute_id = '36') AS bucket; 

Ich habe in den folgenden Indizes auf diese definiert:

KEY `idx_bucket` (`attribute_id`,`string_value`) 
KEY `idx_self_join` (`patient_sid`,`attribute_id`,`lft`,`rgt`) 

Wenn ich mir die Abfrage Mit EXPLAIN ist die Unterabfrage, die den Deckungsindex idx_bucket verwendet, definitiv optimiert, aber die self-join-und where-Klausel nicht. Darüber hinaus, warum meldet es, dass nur patient_sid und attribute_id für used_key_parts verwendet werden, während eine attachment_condition für lft, rgt (Was bedeutet das?). Sowohl lft als auch 'rgt` sind nur als Ganzzahlen ohne besondere Eigenschaften definiert, also warum werden sie nicht in meinem Deckungsindex verwendet?

Noch seltsamer ist, wenn ich definieren

KEY `idx_self_join` (`patient_sid`,`lft`,`rgt`,`attribute_id`) 

nur patient_sid registriert in used_key_parts.filtered Außerdem Tropfen auf 1.60% von 11.00%!

{ 
    "query_block": { 
    "select_id": 1, 
    "cost_info": { 
     "query_cost": "645186.71" 
    }, 
    "nested_loop": [ 
     { 
     "table": { 
      "table_name": "clinical_data", 
      "access_type": "ref", 
      "possible_keys": [ 
      "fk_attribute_idx", 
      "idx_value_string", 
      "idx_value_double", 
      "idx_bucket", 
      "idx_self_join_idx" 
      ], 
      "key": "idx_bucket", 
      "used_key_parts": [ 
      "attribute_id", 
      "string_value" 
      ], 
      "key_length": "308", 
      "ref": [ 
      "const", 
      "const" 
      ], 
      "rows_examined_per_scan": 126402, 
      "rows_produced_per_join": 126402, 
      "filtered": "100.00", 
      "cost_info": { 
      "read_cost": "126402.00", 
      "eval_cost": "25280.40", 
      "prefix_cost": "151682.40", 
      "data_read_per_join": "46M" 
      }, 
      "used_columns": [ 
      "patient_sid", 
      "string_value", 
      "attribute_id", 
      "lft", 
      "rgt" 
      ], 
      "attached_condition": "(`ns_large2`.`clinical_data`.`patient_sid` is not null)" 
     } 
     }, 
     { 
     "table": { 
      "table_name": "clinical_data", 
      "access_type": "ref", 
      "possible_keys": [ 
      "fk_attribute_idx", 
      "idx_value_string", 
      "idx_value_double", 
      "idx_bucket", 
      "idx_self_join_idx" 
      ], 
      "key": "idx_self_join_idx", 
      "used_key_parts": [ 
      "attribute_id", 
      "patient_sid" 
      ], 
      "key_length": "10", 
      "ref": [ 
      "const", 
      "ns_large2.clinical_data.patient_sid" 
      ], 
      "rows_examined_per_scan": 14, 
      "rows_produced_per_join": 201169, 
      "filtered": "11.11", 
      "using_index": true, 
      "cost_info": { 
      "read_cost": "131327.39", 
      "eval_cost": "40233.83", 
      "prefix_cost": "645186.71", 
      "data_read_per_join": "73M" 
      }, 
      "used_columns": [ 
      "patient_sid", 
      "attribute_id", 
      "lft", 
      "rgt" 
      ], 
      "attached_condition": "((`ns_large2`.`clinical_data`.`lft` >= `ns_large2`.`clinical_data`.`lft`) and (`ns_large2`.`clinical_data`.`rgt` <= `ns_large2`.`clinical_data`.`rgt`))" 
     } 
     } 
    ] 
    } 
} 

Antwort

1

Hier ist Ihr Grund JOIN:

SELECT 

FROM clinical_data cd1 

JOIN clinical_data cd2 
    ON cd1.patient_sid = cd2.patient_sid 
    AND cd2.attribute_id = '33' 

WHERE cd1.attribute_id = '36' 
+0

Richtig, aber 'lft' und' rgt' definieren die Kanten der verschachtelten Menge, was mir eine Menge von Datensätzen gibt. Ihre Abfrage würde nicht die richtigen Ergebnisse liefern. Ich könnte 'lft' und' rgt's Bereichsberechnungen in die Where-Klausel schreiben, aber das wäre wahrscheinlich auch nicht optimal. –

+0

Ich habe das alles nicht zur besseren Übersicht hinzugefügt. Sie können es immer noch hinzufügen. Oder nur einen Moment und ich werde für dich. – dkretz

+0

Erledigt: Das Verschieben dieser Werte in die where-Klausel wurde gerade von ungefähr 20 Sekunden von der Ausführungszeit entfernt. –

0

"Used_columns" sagt, dass es ist 'bedeckt'. Die endgültigen "gebrauchten Schlüsselteile" werden nicht alle als "Schlüssel" verwendet, da sie in einem "Bereich" benötigt werden, nicht "=".

Sie sich von der äußeren Abfrage los:

 SELECT clinical_data.patient_sid, clinical_data.lft, clinical_data.rgt 
      FROM clinical_data 
      INNER JOIN 
       (SELECT clinical_data.patient_sid, clinical_data.lft, clinical_data.rgt, 
         clinical_data.attribute_id 
        FROM clinical_data 
        WHERE clinical_data.attribute_id = '33' 
         AND clinical_data.string_value = '2160-0' 
      ) AS attribute ON clinical_data.patient_sid = attribute.patient_sid 
       AND clinical_data.lft >= attribute.lft 
       AND clinical_data.rgt <= attribute.rgt 
      WHERE clinical_data.attribute_id = '36' 

Sorry, aber das LFT-RGT-Schema ist nicht sehr effizient.

+0

Und auch die innere Abfrage. Nur SELECT ... VON klinischen_Daten cd1 INNER JOIN klinischen_Daten CD2. – dkretz

+0

Verstanden. Danke für die Klarstellung. Leider muss ich die äußere Abfrage verwenden, da dies eine verschachtelte Mengenstruktur ist. –

1

Hier ist, was schließlich kam ich mit:

SELECT 
    cd1.patient_sid as sid 

FROM clinical_data cd1 

JOIN clinical_data cd2 
    ON cd1.patient_sid = cd2.patient_sid 
    AND cd1.lft >= cd2.lft 
    AND cd1.rgt <= cd2.rgt 

WHERE cd1.attribute_id = '36' 
    AND cd2.attribute_id = '33' 
    AND cd2.string_value = '2160-0' 
+0

Das Verschieben von lft und rgt in die where-Klausel hat das für mich ziemlich beschleunigt. –