Хотите узнать, как улучшить медленный запрос mysql

У меня есть запрос MySQL, чтобы выбрать все идентификаторы продукта с определенными фильтрами, примененными к продуктам. Этот запрос работает, но я хочу научиться улучшать этот запрос. Альтернативы этому запросу приветствуются с объяснением.

SELECT kkx_products.id from kkx_products WHERE display = 'yes' AND id in
    (SELECT product_id FROM `kkx_filters_products` WHERE `filter_id` in 
       (SELECT id FROM `kkx_filters` WHERE kkx_filters.urlname = "comics" OR kkx_filters.urlname = "comicsgraphicnovels") 
    group by product_id having count(*) = 2) 
    ORDER BY kkx_products.id desc LIMIT 0, 24 

Я включил структуру таблиц, используемых в запросе.

EXPLAINkkx_filters;

Field            Type                 Null  Key     Default        Extra
id               int(11) unsigned     NO    PRI     NULL           auto_increment
name             varchar(50)          NO             
filtergroup_id   int(11)              YES   MUL     NULL     
urlname          varchar(50)          NO    MUL     NULL     
date_modified    timestamp            NO            CURRENT_TIMESTAMP    
orderid          float(11,2)          NO            NULL    

EXPLAIN kkx_filters_products;

Field            Type                 Null  Key   Default          Extra
filter_id        int(11)              NO    PRI   0    
product_id       int(11)              NO    PRI   0   

ОБЪЯСНИТЬ kkx_products;

Field            Type                 Null  Key   Default          Extra
id               int(11)              NO    PRI   NULL             auto_increment
title            varchar(255)         NO           
urlname          varchar(50)          NO    MUL        
description      longtext             NO          NULL   
price            float(11,2)          NO          NULL   
orderid          float(11,2)          NO          NULL   
imageurl         varchar(255)         NO            
date_created     datetime             NO          NULL    
date_modified    timestamp            NO          CURRENT_TIMESTAMP    
created_by       varchar(11)          NO          NULL    
modified_by      varchar(11)          NO          NULL   
productnumber    varchar(32)          NO           
instock          enum('yes','no')     NO          yes    
display          enum('yes','no')     NO          yes    

person Tim van den Eijnden    schedule 06.05.2011    source источник
comment
Если бы я задал этот вопрос, я бы упорно работал над тем, чтобы форматирование (читай: столбцы) было на 100% правильным, чтобы вопрос был привлекательным для читателей.   -  person Uwe Keim    schedule 06.05.2011


Ответы (1)


Вместо использования встроенных запросов в операторах критериев попробуйте использовать блок EXISTS ... http://dev.mysql.com/doc/refman/5.0/en/exists-and-not-exists-subqueries.html

Вы сможете увидеть разницу в своем плане объяснения. Раньше у вас был запрос, выполняющийся для каждой записи в вашем наборе результатов, и каждый результат в этом наборе результатов встроенного представления имел свой собственный запрос, выполняемый для.

Вы видите, как вложенные встроенные представления могут привести к экспоненциальному увеличению стоимости. EXISTS так не работает.

Пример использования EXISTS:

Предположим, что tbl1 имеет идентификатор столбца и данные. tbl2 имеет идентификатор столбца, родительский элемент и данные.

SELECT a.*
FROM tbl1 a
WHERE 1 = 1 
AND EXISTS (
  SELECT NULL 
  FROM tbl2 b
  WHERE b.parentid = a.id 
  AND b.data = 'SOME CONDITIONAL DATA TO CONSTRAIN ON'
)

1) Мы можем предположить, что 1 = 1 - это какое-то условие, которое приравнивается к истине для каждой записи 2) На самом деле не имеет значения, что мы выбираем в статусе EXISTS, NULL в порядке. 3) Важно посмотреть на b.parentid = a.id, это связывает наш оператор exist с набором результатов

person maple_shaft    schedule 06.05.2011
comment
То, что сказал @maple_shaft, плюс убедитесь, что у вас есть индексы в правильных столбцах, а также используйте соединения, где это необходимо (например, при получении фильтров по продуктам). - person Christopher; 06.05.2011
comment
Я читал документацию по EXISTS, но не могли бы вы привести пример? - person Tim van den Eijnden; 06.05.2011
comment
Я также сделал то, что сказал @Christopher, по возможности используйте объединения. SQL-запрос: `SELECT product_id id FROM kkx_filters_products LEFT JOIN kkx_filters ON filter_id = kkx_filters.id LEFT JOIN kkx_products ON product_id = kkx_products.id WHERE filter_id IN (SELECT id FROM_filters_products.id WHERE filter_id IN (SELECT id FROM_kfilters_products.id WHERE filter_id IN (SELECT id FROM_kfilters_products.id WHERE filter_id IN) (SELECT id FROM_kfilters_products.id WHERE filter_id IN) (SELECT id FROM_kfilters_filters) kkxE_filters_filters_filters_filters_filters_filters_filters_filters_filters_filters_filters_filters_filters_filters_filters_filters_filters_filters_filters с_filters_filters_filters_filters} kkx_products.display = 'yes' ГРУППА ПО product_id ИМЕЕТ count (*) = 2 LIMIT 0, 60` - person Tim van den Eijnden; 06.05.2011
comment
Большое спасибо за объяснение, действительно полезно! - person Tim van den Eijnden; 07.05.2011