高查询执行时间

High query execution time

SELECT T.xhrs, T.eq_id, mt.CATEGORY, mt.MODEL_NAME,
       ROUND((SUM (T.TOT_AVAIL_TIME-T.maintenance_TIME) / SUM(T.TOT_AVAIL_TIME))*100) AVAILABILITY,
       ROUND((SUM(UTIL_TIME) / nullif(SUM(T.TOT_AVAIL_TIME-T.maintenance_TIME ),0) )*100) UTILIZATION,
       ROUND(SUM(T.failedcmds)/
       SUM(T.total_failedcmds),2)*100 failedcmds,
       AVG(MAX_QL) MAX_QL,
       AVG(AVG_QL) avg_ql
FROM db1 T,
     db2 mt
WHERE T.eq_model = mt.eq_model
  and TOT_AVAIL_TIME != 0
  AND TOT_AVAIL_TIME  IS NOT NULL
GROUP BY T.xhrs, T.eq_id, mt.CATEGORY, mt.MODEL_NAME

此查询 returns 2550 条记录,在 SQL 开发人员中 运行 需要 12-15 秒,而在 mybatis 中需要 30-35 秒。现有查询有什么问题吗?有什么方法可以优化上述查询并将 sql 开发人员的执行时间降低到 <5 秒,ORM 中的执行时间降低到 <15 秒?

解释计划

eq_model 列上添加索引并检查


请仅尝试使用此查询,我在 TOT_AVAIL_TIM

上组合了 where 条件
SELECT T.xhrs, T.eq_id, mt.CATEGORY, mt.MODEL_NAME,
       ROUND((SUM (T.TOT_AVAIL_TIME-T.maintenance_TIME) / SUM(T.TOT_AVAIL_TIME))*100) AVAILABILITY,
       ROUND((SUM(UTIL_TIME) / nullif(SUM(T.TOT_AVAIL_TIME-T.maintenance_TIME ),0) )*100) UTILIZATION,
       ROUND(SUM(T.failedcmds)/
       SUM(T.total_failedcmds),2)*100 failedcmds,
       AVG(MAX_QL) MAX_QL,
       AVG(AVG_QL) avg_ql
FROM db1 T,
     db2 mt
WHERE T.eq_model = mt.eq_model
  AND (TOT_AVAIL_TIME != 0 AND TOT_AVAIL_TIME  IS NOT NULL)
GROUP BY T.xhrs, T.eq_id, mt.CATEGORY, mt.MODEL_NAME

如果表还没有正确索引,您可以通过 TOT_AVAIL_TIMET.eq_model 索引 T 和 [=[=] 索引 mt 来获得最大收益14=]

T.eq_modelT.TOT_AVAIL_TIME放在一个索引中(按此顺序)。

注意:由于您还检查 TOT_AVAIL_TIME 的 NULL 性,我假设它可以根据列定义为 NULL。如果在简单索引中对其进行索引,则 NULL-s 不会被索引,并且 TOT_AVAIL_TIME IS NOT NULL 稍后将不会使用该索引。因此,要么将其与 eq_model 结合使用,要么删除该过滤器并将列更改为 NOT NULL.

我在 JIRA 上的可空列上使用了这个解决方法:(PROJECT_CAN_HAS_NULL ASC, '1')

让我提出几点让我们思考性能。

事实上"MyBatis or any other ORM is going to be slower than native SQL execution"。造成这一事实的一些原因是:

  • R1。很明显,MyBatis 增加了数据库调用的开销。您获得了灵活性、维护性和封装性,但是却失去了性能。
  • R2。在大多数情况下,MyBatis 会将 ResultSet 解析为 Java 个对象,这会增加额外的开销。 SQL 客户可以直接使用更快的游标,但在较长的 运行 中可能更难维护。
  • R3。在大多数情况下,MyBatis 会为你创建一个事务,这会增加额外的开销。
  • R4。在大多数情况下,MyBatis 会为您创建和管理一个缓存,这会增加前 select 的额外开销,但会加快接下来 select 的过程。
  • R5。 MyBatis 还可以帮助您进行延迟加载和其他数据检索策略。 -R6。我们应该将 MyBatis 执行与 JDBC 执行进行比较。不要将 MyBatis 与 SQL 客户端工具(例如 SQL Developer)进行比较,因为有些变量会掩盖您的结果。例如,他们可能不会一次获取所有行。

话虽这么说,MyBatis 可能会为您提供灵活性、更好的维护、处理事务的简单方法、将表解析为 Java 对象的简单方法,但您需要一些性能。

因此,如果您想加快查询速度,则应考虑以下几点。见 MyBatis Documentation:

  • C1。在查询中使用 fetchSize。
  • C2。明智地使用缓存,看看需要什么样的缓存,在某些情况下根本不使用缓存是有意义的。示例:<select ... useCache="false">
  • C3。请注意 "N+1 Selects Problem"。该文档对许多 ORM 的这一特性有一些见解。
  • C4。尝试使用轻量级事务管理器,例如 "JDBC",请记住面向方面的事务(例如 Spring @Transactional)会增加一些开销。