高查询执行时间

时间:2016-02-25 14:27:12

标签: sql oracle orm mybatis

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

此查询返回2550条记录,需要12-15秒才能在SQL Developer中运行,而在mybatis中则需要30-35秒。现有查询有什么问题吗?是否有任何方法可以优化上述查询并将执行时间降低到sql developer中的<5秒和ORM中的<15秒?

解释计划

enter image description here

4 个答案:

答案 0 :(得分:1)

让我提出几点让我们考虑一下表现。

事实上,“MyBatis或任何其他ORM将比本机SQL执行慢”。这个事实的一些原因是:

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

话虽这么说,MyBatis可以为您提供灵活性,更好的维护,一种简单的方法来处理将表解析为Java对象的事务性,简单方法,但是您可以从中获得一些性能。

因此,如果您想加快查询速度,您应该考虑一些事项。见MyBatis Documentation

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

答案 1 :(得分:0)

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

答案 2 :(得分:0)

如果表格尚未正确编入索引,您可以通过TTOT_AVAIL_TIMET.eq_modelmt编制索引mt.eq_model }

答案 3 :(得分:0)

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

注意:当您还检查TOT_AVAIL_TIME的NULL-ness时,我认为它可以通过列定义为NULL。如果在简单索引中对其进行索引,则不会对NULL-s建立索引,并且TOT_AVAIL_TIME IS NOT NULL以后不会使用该索引。因此,要么将其与eq_model合并,要么删除该过滤器并将列更改为NOT NULL

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

相关问题