【问题标题】:MySQL query execution optimizationMySQL查询执行优化
【发布时间】:2017-01-11 12:16:03
【问题描述】:

我正在寻找一种方法来加速以下示例查询,而无需对数据进行非规范化并将 task_customers 列引入表任务:

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);

在两个表中都有超过 10 万条记录的真实案例场景中执行此查询时,它确实会变慢并创建临时表。因此,我正在寻找一种解决方案,如果可能的话,可以在不进行数据非规范化的情况下加快处理速度。

【问题讨论】:

    标签: mysql many-to-many left-join query-optimization


    【解决方案1】:
    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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-06
      • 2014-02-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-22
      • 2011-07-07
      • 2018-12-21
      相关资源
      最近更新 更多