SQL Query对另一个mysql版本执行速度较慢?

时间:2017-07-01 09:29:35

标签: php mysql sql

目前,我正在开展一个项目,该项目要求我为用户编写API。到目前为止,我已经编写了以下SQL语句,并在我的本地主机上通过我的php进行了测试:

SELECT topquery.kind_id,
       topquery.image,
       topquery.id,
       userquery.user_name
FROM `order` AS topquery,
     `user` AS userquery
WHERE userquery.user_id = topquery.user_id
  AND topquery.id IN
    (SELECT MIN(id)
     FROM `order` AS mainquery
     WHERE user_id != '$vUserId'
       AND id NOT IN
         (SELECT order_id
          FROM history
          WHERE user_id = '$vUserId')
       AND kind_id NOT IN
         (SELECT o.kind_id
          FROM history h
          INNER JOIN `order` o ON h.order_id = o.id
          WHERE h.user_id = '$vUserId')
       AND actions > 0
       AND kind = '1'
     GROUP BY kind_id)
ORDER BY vip DESC
LIMIT 35

此查询在我的本地主机上大约需要0.5秒,在我的服务器上需要大约1.4秒。

现在我的问题: 是否有可能SQL查询的速度因每个mysql版本而异? 或者我的查询不是"优化"足够?

4 个答案:

答案 0 :(得分:0)

是的,它会有所不同,因为每个版本的sql都有不同的调整要优化或代码路径或算法处理速度。我认为最新版本会比之前版本更快。

答案 1 :(得分:0)

关闭主题建议,但我想要格式化以便评论不够

您可以使用where子句

中的连接谓词开始查询
FROM `order` AS topquery,
     `user` AS userquery
WHERE userquery.user_id = topquery.user_id

在查询的更深层次中,您确实使用INNER JOIN语法。那么为什么不一直这样做呢?

FROM `order` AS topquery,
INNER JOIN `user` AS userquery ON userquery.user_id = topquery.user_id

坚持只使用显式连接。不允许自己在from子句中的表之间使用逗号。不要"混合搭配"加入语法,这会导致维护问题和可能的错误。

答案 2 :(得分:0)

在这里,我概述了您的案例的诊断,然后您可以确定速度是否仍然是一个问题:

  1. 网络。我不确定那个时间是纯粹是从SQL执行还是网络时间也在那里。您的网络电话会产生开销。

  2. 这取决于您的服务器是什么,但如果您的环境匹配,几乎总是肯定的,因为您的服务器数据库中的数据远多于您的本地主机。

  3. 在公司环境中拥有共享开发服务器的一个优点是,有人可能会经常为您提供一些数据,因此每个人都不必将所有数据复制到他们的计算机上以使用实际大小数据集。更多数据=更多工作=需要更长时间,更简单。

    1. 您的数据库架构存在差异。如果您不能在一个命令中重建数据库,则可能在localhost上添加了索引并忘记了它。您可以使用模式工具来获取localhost和数据库之间的差异。我喜欢SQLYog。我认为Mysql工作台也是这样做的。

    2. 您的硬件存在差异。即你的服务器是486,内存为4mb。

答案 3 :(得分:0)

服务器之间的性能差异

是的,性能可以在不同的MySQL版本之间变化。原因是整个软件可能会发生变化,包括MySQL优化器,它会计算查询将执行的计划。

在决定MySQL版本是否是根本原因之前,我会检查的几个因素是:

  1. 硬件 - 您的本地主机和服务器上有不同的硬件吗? CPU,内存,硬盘等
  2. 分配的资源 - 您是否在不同服务器上的my.cnf / my.ini配置文件中为MySQL实例提供不同的内存分配?如果是这样,它可以极大地影响MySQL实例的性能。
  3. 缓存 - 也许查询是由其中一个服务器上的MySQL实例缓存的。我建议重启MySQL实例以确保缓存清晰,然后运行查询并比较执行时间。
  4. 数据量 - 您在localhost和第二台服务器上有不同的数据量吗?如果是这样,它会显着影响查询执行时间。
  5. 查询效果

    此外,我查看了您的查询,看起来可以更好地进行优化。

    (我使用EverSQL SQL Query Optimizer来获取建议 - 免责声明,我是EverSQL的联合创始人并谦虚地提供这些建议):

    1. 您可以使用INNER JOIN替换IN子句中的子选择(性能不佳)。
    2. 您可以使用LEFT JOIN替换NOT IN子句中的子选择,这将提高性能。
    3. 此外,当您有复杂的子查询时,可以考虑将它们拆分为临时表并加入这些表。最大的好处是你可以索引该临时表中的列,加入它,一旦会话完成,它将被删除。
    4. 确保添加相关索引(根据列中的数据分布及其基数)。确保索引符合条件的顺序。
    5. 这是优化后查询的样子:

      create table temp as 
      SELECT
                o.kind_id
              FROM
                history h
                INNER JOIN `order` o ON h.order_id = o.id
              WHERE
                h.user_id = '$vUserId';
      
      CREATE INDEX kind_id on temp(kind_id);
      
      create table temp2 as
      SELECT
            MIN(id) as id
          FROM
            `order` AS mainquery
            left join history h on mainquery.id=h.order_id
            left join temp t on mainquery.kind_id=t.kind_id
          WHERE
            user_id != '$vUserId'
            AND h.order id is null
            and t.kind_id is null
            AND actions > 0
            AND kind = '1'
          GROUP BY
            kind_id;    
      
      CREATE INDEX id on temp2(id);
      
      SELECT 
          topquery.kind_id,
          topquery.image,
          topquery.id,
          userquery.user_name
      FROM
          `order` AS topquery,
          `user` AS userquery,
          temp2 AS temp
      WHERE
          userquery.user_id = topquery.user_id
              AND topquery.id = temp.id
      ORDER BY vip DESC
      LIMIT 35