Mysql - 在更好的服务器中,相同的查询要慢得多

时间:2013-09-22 18:49:40

标签: mysql performance settings

我有这样的查询:

SELECT o.id,
        o.archieve,
        listingid,
        orderdate,
        paymentdate,
        os.STATUS,
        o.shippingpreference,
        s.NAME AS store,
        c.fullname AS customer,
        (
            SELECT COUNT(oi.id)
            FROM orders_inventory oi
            WHERE orderid = o.id
        ) AS itemcount,
        (
            SELECT COUNT(op.orderid)
            FROM orders_preorder op
            WHERE op.orderid = o.id
        ) AS itemcountPre,
        a.fullname AS salesrep,
        fOrderProfit(o.id) AS profit,
        o.packtime,
        o.trackingnumber,
        fSentMailToVendor(o.id) AS sentmailtovendors,
        a2.fullname AS adminname
FROM    orders o
        LEFT JOIN orders_status os
                ON os.id = o.statusid
        LEFT JOIN stores s
                ON s.id = o.storeid
        LEFT JOIN customers c
                ON c.id = o.customerid
        LEFT JOIN admins a
                ON a.id = o.salerepresentativeid
        LEFT JOIN admins a2
                ON a2.id = o.adminid
WHERE TRUE AND archieve = '0'
GROUP BY o.id
ORDER BY o.id DESC LIMIT 50

是的,它有点复杂,也许应该进行优化。 但我的问题是,相同的查询在0,4秒内运行在旧服务器(mysql v5.5)中,而在具有两个CPU和更好硬件(mysql v5.6)的服务器中运行300秒。有什么想法吗?


在两台服务器上使用EXPLAIN EXTENDED提供了8行解释,但我相信第一行有所不同,所以我只列出了第一行比较:

旧服务器:

  • select_type:PRIMARY
  • table:o
  • 类型:index
  • possible_keys:Null
  • key:PRIMARY
  • key_len:4
  • ref:Null
  • 行:50
  • 过滤:102776
  • 额外:使用

新服务器:

  • select_type:PRIMARY
  • table:o
  • 类型:ALL
  • possible_keys:PRIMARY,id,orderdate,customerid,storeid
  • key:Null
  • key_len:Null
  • ref:Null
  • 行:51664
  • 过滤:100
  • 额外:使用地点;使用临时;使用filesort

注意:顺便说一句,我在使用EXPLAIN EXTENDED之前将新服务器中的表类型转换为InnoDB。

1 个答案:

答案 0 :(得分:0)

我假设桌面结构是一样的,我很清楚它是什么:

5.6上的优化器与5.5中的优化器非常不同。您应该使用EXPLAIN运行该语句,并查看优化程序为您提供的内容。

您可能需要使用optimizer_switch(打开或关闭设置),或者您可以在语句中添加USE INDEX以告知优化器选择哪条路径。

或者,您可以多次运行查询并“教”优化器采用哪条路径,但肯定无法保证。

我希望有所帮助。

增加新数据:

正如你的解释说明所示,尝试这样的事情:

SELECT o.id,
        o.archieve,
        listingid,
        orderdate,
        paymentdate,
        os.STATUS,
        o.shippingpreference,
        s.NAME AS store,
        c.fullname AS customer,
        (
            SELECT COUNT(oi.id)
            FROM orders_inventory oi
            WHERE orderid = o.id
        ) AS itemcount,
        (
            SELECT COUNT(op.orderid)
            FROM orders_preorder op
            WHERE op.orderid = o.id
        ) AS itemcountPre,
        a.fullname AS salesrep,
        fOrderProfit(o.id) AS profit,
        o.packtime,
        o.trackingnumber,
        fSentMailToVendor(o.id) AS sentmailtovendors,
        a2.fullname AS adminname
FROM    orders o use index (primary) -- new change here
        LEFT JOIN orders_status os
                ON os.id = o.statusid
        LEFT JOIN stores s
                ON s.id = o.storeid
        LEFT JOIN customers c
                ON c.id = o.customerid
        LEFT JOIN admins a
                ON a.id = o.salerepresentativeid
        LEFT JOIN admins a2
                ON a2.id = o.adminid
WHERE TRUE AND archieve = '0'
GROUP BY o.id
ORDER BY o.id DESC LIMIT 50