0

Я следующий запросом с подзапросом и автообъединением:Оптимизации запроса с использованием покрывающих индексов

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; 

I имеет следующие показатели определены на этом:

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

Когда я смотрю на запросе используя EXPLAIN, подзапрос с использованием индекса покрытия idx_bucket определенно оптимизирован, но самосоединение и предложение where не являются. Кроме того, почему он сообщает, что только patient_sid и attribute_id используются для used_key_parts, а attachment_condition показан для lft, rgt (что это означает?). Оба lft и 'rgt` просто определены как целые числа без специальных свойств, поэтому почему они не используются в моем индексе покрытия?

Еще более странно, когда я определяю

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

только patient_sid зарегистрирован в used_key_parts. Кроме того filtered капель на 1.60% от 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`))" 
     } 
     } 
    ] 
    } 
} 

ответ

1

Вот ваш основной 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

Правильно, но 'lft' и' rgt' определяют ребра вложенного набора, что дает мне набор записей. Ваш запрос не даст правильных результатов. Я мог бы использовать вычисления lft и rgt в предложении where, но это тоже, вероятно, не было бы оптимальным. –

+0

Я просто не включил все это для ясности. Вы можете добавить его. Или минут, и я буду за тебя. – dkretz

+0

Выполнено: Фактически, переместите их в предложение where, только что выбритое около 20 секунд от времени выполнения. –

0

"Used_columns" говорит, что является 'покрытие'. Конечные «используемые ключевые части» не все используются как «ключ», потому что они необходимы в «диапазоне», а не «=».

Избавьтесь от внешнего запроса:

 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' 

Извините, но LFT-RGT схема не очень эффективным.

+0

а также внутренний запрос. Только SELECT ... FROM clinicaldata cd1 INNER JOIN clinic_data cd2. – dkretz

+0

Получил это. Спасибо за разъяснения. К сожалению, мне нужно использовать внешний запрос, так как это вложенная структура набора. –

1

Вот что я наконец придумал:

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

Перемещение lft и rgt в предложение where ускорило это для меня совсем немного. –

Смежные вопросы