0

我在一些查询上遇到了 MySQL(5.5 版)左连接性能的问题。在所有情况下,我都能够通过使用联合和子选择重组查询来解决这个问题(我在《高性能 MySQL 》一书中看到了一些例子)。问题是这会导致非常混乱的查询。

下面是产生完全相同结果的两个查询的示例。第一个查询比第二个查询慢大约两个数量级。第二个查询比第一个查询可读性差得多。

据我所知,这些类型的查询并没有因为索引错误而表现不佳。在所有情况下,当我重组查询时,它运行得很好。我还尝试仔细查看索引并使用提示无济于事。

有没有其他人遇到过类似的 MySQL 问题?我应该尝试调整任何服务器参数吗?有没有人找到一种更清洁的方法来解决这类问题?

查询 1

select
  i.id,
  sum(vp.measurement * pol.quantity_ordered) measurement_on_order
from items i
left join (vendor_products vp, purchase_order_lines pol, purchase_orders po) on
  vp.item_id = i.id and
  pol.vendor_product_id = vp.id and
  pol.purchase_order_id = po.id and
  po.received_at is null and
  po.closed_at is null
group by i.id

explain:
+----+-------------+-------+--------+-------------------------------+-------------------+---------+-------------------------------------+------+-------------+
| id | select_type | table | type   | possible_keys                 | key               | key_len | ref                                 | rows | Extra       |
+----+-------------+-------+--------+-------------------------------+-------------------+---------+-------------------------------------+------+-------------+
|  1 | SIMPLE      | i     | index  | NULL                          | PRIMARY           | 4       | NULL                                |  241 | Using index |
|  1 | SIMPLE      | po    | ref    | PRIMARY,received_at,closed_at | received_at       | 9       | const                               |    2 |             |
|  1 | SIMPLE      | pol   | ref    | purchase_order_id             | purchase_order_id | 4       | nutkernel_dev.po.id                 |    7 |             |
|  1 | SIMPLE      | vp    | eq_ref | PRIMARY,item_id               | PRIMARY           | 4       | nutkernel_dev.pol.vendor_product_id |    1 |             |
+----+-------------+-------+--------+-------------------------------+-------------------+---------+-------------------------------------+------+-------------+

查询 2

select
  i.id,
  sum(on_order.measurement_on_order) measurement_on_order
from (
  (
    select
      i.id item_id,
      sum(vp.measurement * pol.quantity_ordered) measurement_on_order
    from purchase_orders po
    join purchase_order_lines pol on pol.purchase_order_id = po.id
    join vendor_products vp on pol.vendor_product_id = vp.id
    join items i on vp.item_id = i.id
    where
      po.received_at is null and po.closed_at is null
    group by i.id
  )
  union all
  (select id, 0 from items)
) on_order
join items i on on_order.item_id = i.id
group by i.id

explain:
+------+--------------+------------+--------+-------------------------------+--------------------------------+---------+-------------------------------------+------+----------------------------------------------+
| id   | select_type  | table      | type   | possible_keys                 | key                            | key_len | ref                                 | rows | Extra                                        |
+------+--------------+------------+--------+-------------------------------+--------------------------------+---------+-------------------------------------+------+----------------------------------------------+
|  1   | PRIMARY      | <derived2> | ALL    | NULL                          | NULL                           | NULL    | NULL                                | 3793 | Using temporary; Using filesort              |
|  1   | PRIMARY      | i          | eq_ref | PRIMARY                       | PRIMARY                        | 4       | on_order.item_id                    |    1 | Using index                                  |
|  2   | DERIVED      | po         | ALL    | PRIMARY,received_at,closed_at | NULL                           | NULL    | NULL                                |   20 | Using where; Using temporary; Using filesort |
|  2   | DERIVED      | pol        | ref    | purchase_order_id             | purchase_order_id              | 4       | nutkernel_dev.po.id                 |    7 |                                              |
|  2   | DERIVED      | vp         | eq_ref | PRIMARY,item_id               | PRIMARY                        | 4       | nutkernel_dev.pol.vendor_product_id |    1 |                                              |
|  2   | DERIVED      | i          | eq_ref | PRIMARY                       | PRIMARY                        | 4       | nutkernel_dev.vp.item_id            |    1 | Using index                                  |
|  3   | UNION        | items      | index  | NULL                          | index_new_items_on_external_id | 257     | NULL                                | 3380 | Using index                                  |
| NULL | UNION RESULT | <union2,3> | ALL    | NULL                          | NULL                           | NULL    | NULL                                | NULL |                                              |
+------+--------------+------------+--------+-------------------------------+--------------------------------+---------+-------------------------------------+------+----------------------------------------------+
4

0 回答 0