【问题标题】:Mysql - the same query is much more slower in better serverMysql - 在更好的服务器中相同的查询要慢得多
【发布时间】:2013-09-27 15:47:06
【问题描述】:

我有一个这样的查询:

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

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


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

旧服务器:

  • select_type:主要
  • 表:o
  • 类型:索引
  • 可能的键:空
  • 键:主键
  • key_len: 4
  • 参考:空
  • 行数:50
  • 过滤:102776
  • 额外:使用 where

新服务器:

  • select_type:主要
  • 表:o
  • 类型:全部
  • possible_keys: PRIMARY,id,orderdate,customerid,storeid
  • 键:空
  • key_len:空
  • 参考:空
  • 行数:51664
  • 过滤:100
  • 额外:使用 where;使用临时的;使用文件排序

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

【问题讨论】:

  • 两个数据库中源表的索引是什么?
  • 索引为 o.id,oi.id,os.id,o.statusid,s.id,o.storeid,c.id,o.customerid 和 a.id。它们对于两个数据库都是相同的,因为我将整个数据库从旧服务器复制到新服务器。我也尝试分析表格等,但没有奏效。
  • 你对比过两台服务器上的解释吗?
  • 我刚刚在问题中添加了比较结果。谢谢。
  • 你运行ANALYZE TABLE了吗?

标签: mysql performance settings


【解决方案1】:

我假设表结构是相同的,我很清楚它可能是什么:

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

【讨论】:

  • 表结构一开始是一样的,后来我把新的服务器表改成了InnoDB。我还在问题中添加了 EXPLAIN 结果。多次运行相同的查询并没有产生大的变化。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-05
  • 2011-09-20
相关资源
最近更新 更多