2017-01-11 8 views
0

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

SELECT 
    tasks.id, 
    tasks.title, 
    COALESCE(tasksWithOnlyOneCustomer.task_customers, tasksWithMoreThanOneCustomer.task_customers) task_customers 

FROM tasks 

LEFT JOIN (
    SELECT 
     tcl.task_id, 
     GROUP_CONCAT(CONCAT(c.first_name, ' ', c.last_name) SEPARATOR ', ') task_customers, 
     COUNT(tcl.customer_id) c 
    FROM tasks_customers_links tcl 
    LEFT JOIN customers c ON c.id = tcl.customer_id 
    WHERE c.id IS NOT NULL 
    GROUP BY tcl.task_id 
    HAVING c = 1 
) tasksWithOnlyOneCustomer ON tasksWithOnlyOneCustomer.task_id = tasks.id 

LEFT JOIN (
    SELECT 
     tcl.task_id, 
     GROUP_CONCAT(CONCAT(c.first_name, ' ', c.last_name) SEPARATOR ', ') task_customers, 
     COUNT(tcl.customer_id) c 
    FROM tasks_customers_links tcl 
    LEFT JOIN customers c ON c.id = tcl.customer_id 
    WHERE c.id IS NOT NULL 
    GROUP BY tcl.task_id 
    HAVING c > 1 
) tasksWithMoreThanOneCustomer ON tasksWithMoreThanOneCustomer.task_id = tasks.id 

ORDER BY 
    ISNULL(tasksWithOnlyOneCustomer.task_customers) ASC, /* ORDER NULLS AT THE END */ 
    tasksWithOnlyOneCustomer.task_customers ASC, 
    ISNULL(tasksWithMoreThanOneCustomer.task_customers) ASC, /* ORDER NULLS AT THE END */ 
    tasksWithMoreThanOneCustomer.task_customers ASC 

Структура таблицы выглядит следующим образом:

CREATE TABLE tasks (
    id INT NOT NULL, 
    title VARCHAR(255) NOT NULL, 
    PRIMARY KEY (id) 
); 

CREATE TABLE customers (
    id INT NOT NULL, 
    first_name VARCHAR(255) NOT NULL, 
    last_name VARCHAR(255) NOT NULL, 
    PRIMARY KEY (id) 
); 

CREATE TABLE tasks_customers_links (
    id INT NOT NULL AUTO_INCREMENT, 
    task_id INT NOT NULL, 
    customer_id INT NOT NULL, 
    PRIMARY KEY (id), 
    FOREIGN KEY (task_id) REFERENCES tasks(id), 
    FOREIGN KEY (customer_id) REFERENCES customers(id) 
); 

INSERT INTO tasks (id, title) VALUES (1, 'Wake Up!'), (2, 'Eat!'), (3, 'Sleep!'); 
INSERT INTO customers (id, first_name, last_name) VALUES (1, 'Homer', 'Simpson'), (2, 'Bart', 'Simpson'), (3, 'Marge', 'Simpson'); 
INSERT INTO tasks_customers_links (task_id, customer_id) VALUES (1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (3, 3); 

При выполнении этого запроса в сценарии реального случая с более чем 100k записями в обеих таблицах он действительно замедляется и создает временные таблицы. Поэтому я ищу решение для ускорения процесса, если это возможно, без денормализации данных.

ответ

0
select t.id, 
    t.title, 
    coalesce(group_concat(concat(c.first_name, ' ', c.last_name) separator ', '), '') as customers 
    from tasks t 
    left join tasks_customers_links l on l.task_id = t.id 
    left join customers c on l.customer_id = c.id 
    group by 1, 2 
    order by 
    count(c.id) = 0, 
    count(c.id)