不要以为查询执行快一秒钟

我一直遇到RDBMS用户认为执行查询的一秒钟几乎快的情况。 最近,在此堆栈溢出问题中:

Hibernate SQL In子句使CPU使用率达到100%

发布者最初的问题是,为什么类似的查询在SQL Server Management Studio中执行时在一秒钟内执行,而(看似)同一查询从Hibernate执行时却在60秒内执行。 该查询类似于以下内容:

select Student_Id 
from Student_Table 
where Roll_No in ('A101','A102','A103',.....'A250');

这种差异可能有很多原因。 最有可能的是,某个地方还隐藏着一个Hibernate N + 1问题 。 但是,这里最引人注目的信息是:

请不要相信1秒很快。

数据库的运行速度非常快,即使在性能中等的服务器上,上述查询也几乎不会立即执行。 即使在笔记本电脑上! Markus Winand明确指出,在所有性能问题的80%中,您要做的就是添加缺失的索引 。 在这里也是如此!

发布者的原始表仅包含两个索引:

CREATE TABLE student_table (
       Student_Id BIGINT NOT NULL IDENTITY
     , Class_Id BIGINT NOT NULL
     , Student_First_Name VARCHAR(100) NOT NULL
     , Student_Last_Name VARCHAR(100)
     , Roll_No VARCHAR(100) NOT NULL
     , PRIMARY KEY (Student_Id)
     , CONSTRAINT UK_StudentUnique_1 
         UNIQUE  (Class_Id, Roll_No)
);

有一个实现PRIMARY KEY的索引,还有一个用于UNIQUE约束的索引,但是这两个索引并不是非常有用,因为查询谓词基于Roll_No过滤,而Roll_No只是UNIQUE约束的第二列。 在大约800万行上执行上述查询时,我对UNIQUE索引进行了索引扫描,查询在三秒钟内运行:

计划1

此“索引扫描”操作根本不好。 我实际上正在遍历所有索引,以在每个索引叶节点中找到所有适用的Roll_No值。 在“ 使用索引卢克”中有关级联索引的页面中对此进行了很好的解释。

解决方案

但是好消息是,SQL Server Management Studio为您提供了即时调整建议。 只需右键单击执行计划,然后选择“缺少索引详细信息…”即可获得以下建议:

/*
Missing Index Details from SQLQuery1.sql -
    LUKAS-ENVY\SQLEXPRESS.test
The Query Processor estimates that implementing the 
    following index could improve the query cost 
    by 87.5035%.
*/

/*
USE [test]
GO
CREATE NONCLUSTERED INDEX [<Name of Missing Index>]
ON [dbo].[student_table] ([Roll_No])
INCLUDE ([Student_Id])
GO
*/

这并不一定意味着上面的索引是所有查询的最佳选择,但是您使用Roll_No上的谓词进行查询的事实应该足以表明您至少应该在该Roll_No上具有索引柱。 这里最简单的索引就是:

CREATE INDEX i_student_roll_no
ON student_table (Roll_No);

有了该索引,我们现在将获得一个“索引查找”操作,该操作将立即运行:

计划2

覆盖指数

在这种特殊情况下, 弗拉德·米哈尔西娅(Vlad Mihalcea)在其回答中建议“覆盖指数”可能是适当的。 例如:

CREATE INDEX i_student_roll_no
ON student_table (Roll_No, Student_Id);

覆盖索引的优点是查询执行所需的所有信息已包含在索引中 。 在这种特殊情况下,这是正确的,但由于以下情况也可能很危险:

  • 覆盖索引需要更多空间,如果表已经很大,则空间可能成为问题
  • 只要查询不使用其他列(例如,用于投影,计算,其他过滤,排序等),覆盖索引也只会增加值。 在这个简单的示例中可能不是这种情况,在不久的将来可能会Swift改变

因此,在这种情况下,覆盖索引不应成为您的默认选择。 最好保守一些,只在索引中添加为过滤添加立即值的那些列。

结论

我想一次又一次地重复:

不要以为一秒快

事实上:

不要以为,任何超出2-3ms为快!

除非您要进行繁重的报告或批处理,否则处理时间显然可能需要更长的时间,因此像这样的简单查询绝不会比Instant慢。 在大多数情况下,您可以通过添加索引来达到这种速度。

在旁注

显然,上述问题的发布者还存在其他问题。 以上内容都无法解释Hibernate和“普通SQL”之间的执行速度差异。 但是,这里再次传达的信息是,如果您的“普通SQL”已经花费了超过一秒钟的时间,那么您就可以解决问题。

翻译自: https://www.javacodegeeks.com/2015/04/do-not-think-that-one-second-is-fast-for-query-execution.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值