从性能的角度来看,来自应用程序的数据库连接是否昂贵?

chr*_*ris 4 performance sql-server-2008 sql-server connection-pooling connections

一位同事告诉我,连接到数据库的成本很高,而且可能会损害应用程序的性能。他们让我创建一个调用另外 8 个过程的过程,这样他们调用一个过程并取回 8 个数据集。从我的角度来看,SQL 必须等待每个数据集返回,然后才能开始检索下一个数据集,这样也会产生负面影响。

任何人都可以量化应用程序的连接成本,并让我知道最好的方法是调用多个过程还是一个主过程?

Sol*_*zky 5

嗯,这有四个主要方面:

  1. 既然应该首先检查其他三个来源,其中一个是确定性的而不是意见,那么您为什么要向一般的 Internet 征求意见:

    1. 当有人告诉你一条技术/科学信息时,只要有可能,问问他们他们是如何知道情况是这样的。他们在什么地方读过吗?如果是这样,它是一个有信誉的消息来源,还是在他们几年前的一次谈话中顺便提到的,他们只是部分关注,也从未问过个人他们是如何知道这些信息的。如果它是一篇文章/博客文章,请要求查看它,以便您可以自己阅读。如果他们进行了一些测试,请要求查看测试脚本,以便您可以自己运行它们。

      关键是,很多人说了很多事情,有时会诚实地相信绝对不真实的信息的有效性。因此,您不要只相信他们的话,而且应该询问传达信息的人为什么他们认为这是真的。他们的回答可以证明在几个层面上非常有见地:-)。

    2. 无论您能否从提出技术主张的人那里得到答案,请自行研究。进行一些搜索以查看是否已经撰写了关于此主题的技术文章。简单地搜索“数据库连接性能”返回了相当多的文章。只是要警惕随机的博客帖子,因为人们有时会发布他们认为是真实但实际上并非如此的信息。这让我们......

    3. 技术问题的绝对最佳信息来源,尤其是关于“方法 A 比方法 B 快还是慢”类型的问题,是系统本身。谁在乎你的同事说了什么,甚至是其他任何人,不管他们多么受尊重,当你的系统将按照它的行为方式行事并且无法与之争辩时。如果有人说在一次调用数据库中调用 8 个 procs 比 8 个连接快,那么,请尝试两者,看看哪个更快。当然,您可能会或可能不会正确地做事,但是一旦您设置了测试并获得了一些结果,您就可以展示这些结果,看看您是否以某种方式错过了什么。您还可以检查已写的文章,看看它们是否是您错过的技巧或选项。

  2. 一般来说,是的,建立新连接的成本很高,这就是连接池存在的原因。它使连接保持打开状态,以便同一客户端可以重新使用它。建立一个全新的连接需要分配内存,检查安全性,如果在使用 Active Directory 的环境中使用 Windows 身份验证,这可能涉及向另一台服务器发出请求(因为身份验证信息,如果尚未缓存,驻留在域控制器上) . 使用连接池时会跳过所有这些开销。如果您使用 .NET 并连接到 Microsoft SQL Server,则默认情况下应启用连接池。但是你应该检查以确保它正在被使用。

    无论是否使用连接池,单个查询批处理中的多个调用是否比通过单独查询批处理进行的单个调用更快?好吧,如果问题是关闭和重新打开连接的代价很高,那么为什么要关闭连接?为什么不在同一个连接上调用 8 个单独的存储过程?此时唯一的性能差异是发出 7 个附加存储过程请求所需的时间。除非每秒多次调用这组 8 个存储过程,否则这将非常小甚至不值得考虑。这也给我们带来了......

  3. 大多数情况下,性能是规模的函数。有很多低效的操作,每天只被调用一两次,或者每月只调用一次或两次,并没有表现出它们的低效率。但是每分钟甚至一秒执行多次这些操作,同样糟糕的选择会对性能产生巨大影响。在为新字段(无论是新表还是现有表上的新列)选择数据类型时,人们会做出许多错误的选择。他们说,“磁盘很便宜,所以 INT 比 TINYINT 大 3 个字节并不重要,而且这个字段只会保存 1 - 10 的值”。100 甚至 1000 行的额外 3 个字节永远不会(或者我应该说“几乎永远不会”;-) 降低性能。但是,如果 PK,将同一字段作为外键复制到 100 多个表中,并且这些 100 多个表的组合行数在数亿范围内,则会产生影响,并且不仅仅是查询性能,还有备份和恢复时间等。

    那么,这8个存储过程会多久被调用一次呢?如果只有每小时几倍以下,那么你可能不会看到太多的性能差异,你是否调用所有8在一杆,或在同一连接上做8次通话,或者让使用单独的连接8个通话连接池,甚至在不使用连接池的单独连接上进行 8 个单独的呼叫。在这种情况下,您还可以询问您的同事为什么他们甚至担心连接开销以及为什么几乎没有收益的过程过于复杂。

  4. 最后,既然你提到了使用DataSets,这是否意味着如果你一次调用这 8 个存储过程,那么你当时正在将所有8 个结果集完全加载到内存中?如果是,这些结果集有多大?不仅仅是行数,还有每行的大小?是否同时需要所有 8 个结果集?是否总是需要所有 8 个结果集,还是有时只需要一些结果集?这可能是某人在的情况尝试的情况在连接开销上获得一些效率,但实际上为此牺牲了大量内存。如果连接开销真的很大(由于每秒调用 8 个 proc 并且无法使用连接池),那么额外的内存开销可能是值得的。但如果没有,那么您可能会浪费内存来解决最初甚至可能不存在的连接性能问题。