【问题标题】:Time to retrieve a single record via a SQL Server index in a large table是时候通过大表中的 SQL Server 索引检索单个记录了
【发布时间】:2012-01-31 21:45:55
【问题描述】:

问题的简短版本:

如果您有一个包含大量小行的表,并且您想通过可能包含两列的索引从该表中检索一条记录,这可能是低成本和快速或高成本的东西而且慢

加长版问题和背景:

我是一名在一家软件开发公司工作的顾问,我与他们就我想添加到他们正在构建(我正在设计)的应用程序中的一项功能的性能影响发生争执。

目前,每次有人检索客户记录时,我们都会写出一条日志记录。每次检索该记录时,我想将上次访问该记录的人的姓名和时间放在客户端页面上。

他们说这对性能的影响会很大,但根据我对 B 树如何工作的合理但非专业知识,即使表非常大,这似乎也不正确。

如果您在客户记录的 GUID 和访问日期/时间(降序)上创建索引,那么您应该能够通过索引扫描检索所需的记录,这将只需要找到第一个条目为那个 GUID 然后停止?而对于 b-tree 索引,大部分索引都将被缓存,因此所需的物理磁盘访问次数非常少,因此查询时间明显少于 1 秒。

或者我完全错了

【问题讨论】:

  • 您有 GUID 作为键吗?那么您可能已经遇到了潜在的性能问题。
  • @AlbinSunnanbo:你的意思是 GUID 作为一个集群键,我想。
  • 客户和同事总是对性能有奇怪的想法。

标签: sql-server performance indexing


【解决方案1】:

您将遇到 GUID 索引碎片问题,但由于您的行大小没有增加(正如您在 cmets 中所说),您不会遇到页面拆分问题。随机插入问题可以通过重新组织和重建来解决。

除此之外,您的方法没有任何问题。如果表大于 RAM,则每次访问可能只有一个磁盘 IO(中间索引级别将被缓存)。如果您的数据适合 RAM,则每次查询大约需要 0.2 到 0.5 毫秒。如果您的数据在磁盘上,则查找可能需要 8-12 毫秒。在 SSD 上,您会回到 0.2 毫秒到 0.5 毫秒(可能多 0.05 毫秒)。

您为什么不直接创建一些测试数据(通过从 sys.object 的 1M 行中选择一个叉积)并对其进行测量。只需一点时间,您就会发现。

【讨论】:

  • 不确定我是否理解有关增加行大小的评论。每次写入一行时,它的大小都是固定的,不会被更新。并且只是为了理解您的第二段 - 如果该表不适合 RAM(它几乎肯定不会),那么将通过单个磁盘访问来检索所需的行,这将需要 0.5 毫秒?
  • 我们还为每个客户端提供了一个按顺序递增的参考编号,我们可以使用它来代替 GUID。我的理解是,这将消除索引页面碎片/重组的问题。
  • 会的。我添加了一些建议。
  • 谢谢你——这非常有帮助——正是我需要知道的
【解决方案2】:

应该是低成本和快速的,因为列是索引的,我认为这将是 O(n)

【讨论】:

  • 谢谢。抱歉不明白 O(n)。
  • 如果您不知道什么是大 O 表示法,您可能需要在开始对性能做出假设之前进行自学。这可能是一个很好的介绍:stackoverflow.com/questions/3255/…
  • 好的 - 现在不理解大 O(我认为)。如果是这种情况,O(n) 意味着搜索算法在索引中的记录数和时间之间具有线性关系。我的理解是,事实并非如此,一旦索引达到一定大小,就会发生显着增长而不会显着增加搜索时间(前提是页面不会变得碎片化)
【解决方案3】:

你说最后一个访问的人?你的意思是每次读都会写一次?
并且该写入会更改索引的日期时间列?

那我也会担心的。

写入每条记录读取会导致大量额外的磁盘写入。这将阻止读取,并且也可能对您的缓存不利。您还需要大量更新索引,并且由于您更改了索引数据,您的索引将非常碎片化。

【讨论】:

  • 抱歉 - 为了清楚起见,每次有人第一次检索客户端并显示该客户端的摘要页面时,日志文件都会更新;并非每次都读取客户记录 - 这将是一个更高的比率。尽管我们正在将记录添加到日志文件中,但它们并没有被更新。所以我们只是在索引中进行插入。指出写入日志可能会产生影响,但我们已经在这样做了。问题在于以我描述的方式读取这个文件是慢还是快。谢谢你的回复。
【解决方案4】:

视情况而定。

单次检索成本低且速度快

  • 在一个不错的索引表上
  • 在不错的硬件上运行
  • 通过良好的网络

另一方面,这仍然需要时间

如果我们谈论的是每小时一次的检索,请不要为此大汗淋漓。如果我们谈论每秒数千次检索(而不是目前没有),它开始加起来会引起注意。

您需要解决的一些问题

  • 我的硬件是否符合规范
  • 添加两个字段会导致page split (不太可能)
  • 您的常规结果集需要阅读多少额外的页面
  • 每秒将进行多少次检索
  • 每秒插入多少次(触发索引更新)

在您解决了这些问题之后,您应该能够自己做出决定。就我的直觉而言,我会很惊讶你会注意到性能差异。

【讨论】:

  • 谢谢 - 这很有帮助。硬件和网络都OK。我认为我们每隔几秒钟就会进行一次检索(以及正在写入的日志记录)。日志文件列是日期/时间;用户GUID;客户端GUID;访问类型。软件开发人员担心这个文件变大(例如几百万)的影响,但我对 b 树的回忆是它们对文件大小不敏感
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-23
  • 1970-01-01
相关资源
最近更新 更多