1

鉴于此结果集:

mysql> EXPLAIN SELECT c.cust_name, SUM(l.line_subtotal) FROM customer c
    -> JOIN slip s ON s.cust_id = c.cust_id
    -> JOIN line l ON l.slip_id = s.slip_id
    -> JOIN vendor v ON v.vend_id = l.vend_id WHERE v.vend_name = 'blahblah'
    -> GROUP BY c.cust_name
    -> HAVING SUM(l.line_subtotal) > 49999 
    -> ORDER BY c.cust_name;
+----+-------------+-------+--------+---------------------------------+---------------+---------+----------------------+------+----------------------------------------------+
| id | select_type | table | type   | possible_keys                   | key           | key_len | ref                  | rows | Extra                                        |
+----+-------------+-------+--------+---------------------------------+---------------+---------+----------------------+------+----------------------------------------------+
|  1 | SIMPLE      | v     | ref    | PRIMARY,idx_vend_name           | idx_vend_name | 12      | const                |    1 | Using where; Using temporary; Using filesort |
|  1 | SIMPLE      | l     | ref    | idx_vend_id                     | idx_vend_id   | 4       | csv_import.v.vend_id |  446 |                                              |
|  1 | SIMPLE      | s     | eq_ref | PRIMARY,idx_cust_id,idx_slip_id | PRIMARY       | 4       | csv_import.l.slip_id |    1 |                                              |
|  1 | SIMPLE      | c     | eq_ref | PRIMARY,cIndex                  | PRIMARY       | 4       | csv_import.s.cust_id |    1 |                                              |
+----+-------------+-------+--------+---------------------------------+---------------+---------+----------------------+------+----------------------------------------------+
4 rows in set (0.04 sec)

我有点困惑为什么这个语句引用的查询EXPLAIN仍然需要大约一分钟才能执行。这个查询不是必须搜索 449 行吗?任何人都知道什么可能会减慢它的速度?

4

2 回答 2

0

我认为这having sum()是万恶之源。这迫使 mysql 进行两次连接(从customertoslip和 to line)以获取sum. 在此之后,它必须检索所有数据以按sum()值正确过滤以获得有意义的结果。

它可能会针对以下内容进行优化,并且可能会获得更好的响应时间:

select  c.cust_name, 
        grouping.line_subtotal
  from customer c join 
  (select c.cust_id, 
          l.vend_id,
          sum(l.line_subtotal) as line_subtotal 
     from slip s join line l on s.slip_id = l.slip_id
   group by c.cust_id, l.vend_id) grouping 
      on c.cust_id = grouping.cust_id
   join vendor v on v.vend_id = grouping.vend_id 
 where v.vend_name = 'blablah'
   and grouping.line_subtotal > 499999
 group by c.cust_name
 order by c.cust_name;

换句话说,创建一个子选择,在进行真正的查询之前进行所有必要的分组。

于 2013-10-23T08:59:53.957 回答
0

您可以先运行您的选择供应商查询,然后将结果与其余查询合并:

SELECT c.cust_name, SUM(l.line_subtotal) FROM customer c
    -> JOIN slip s ON s.cust_id = c.cust_id
    -> JOIN line l ON l.slip_id = s.slip_id
    -> JOIN (SELECT * FROM vendor WHERE vend_name='blahblah') v ON v.vend_id = l.vend_id 
    -> GROUP BY c.cust_name
    -> HAVING SUM(l.line_subtotal) > 49999 
    -> ORDER BY c.cust_name;

另外,vend_name 和/或 cust_name 有索引吗?这可能是这里的一个问题。

于 2013-10-23T10:29:06.567 回答