13

我在一个网络项目(asp.net)中工作了大约六个月。最终产品即将上线。该项目使用 SQL Server 作为数据库。我们已经对一些大量数据进行了性能测试,结果表明当数据变得太大时性能会下降,比如 200 万行(超时问题、延迟响应等)。起初我们使用完全规范化的数据库,但现在由于性能问题(以减少连接),我们对其进行了部分规范化。首先,这是正确的决定吗?另外,当数据量变得非常大时,可能的解决方案是什么,没有。未来客户增加?

我想进一步补充:

  • 200 万行是实体表,解决关系的表具有更大的行。
  • 当 data + no 时性能下降。的用户增加。
  • 在识别出大量使用的查询后进行非规范化。
  • 我们还使用了大量的 xml 列和 xquery。这可能是原因吗?
  • 有点跑题了,我项目中的一些人说动态 sql 查询比存储过程方法更快。他们已经进行了某种性能测试来证明他们的观点。我认为恰恰相反。一些频繁使用的查询是动态创建的,而其他大多数查询都封装在存储过程中。
4

14 回答 14

30

在事物的方案中,几百万行并不是一个特别大的数据库。

假设我们谈论的是 OLTP 数据库,那么在没有首先确定瓶颈的根本原因的情况下进行非规范化是一个非常非常糟糕的主意

您需要做的第一件事是在一个有代表性的时间段内分析您的查询工作负载,以确定大部分工作在哪里完成(例如,如果您使用的是 SQL Server,则使用 SQL Profiler)。查看查询执行的逻辑读取次数乘以执行的次数。一旦您确定了前十个性能最差的查询,您需要详细检查查询执行计划。

我将在这里四处走动(因为通常是这种情况),但如果您的问题不是,我会感到惊讶

  1. 昂贵查询的“正确”覆盖索引缺失
  2. 配置不当或在指定的磁盘子系统下

SO 答案描述了如何分析以查找工作负载中性能最差的查询。

于 2008-10-03T09:25:49.850 回答
13

正如那句老话所说:“正常化,直到它受伤,非正常化,直到它起作用”。

我喜欢这个!这通常是不能再接受的事情。我可以想象,DBASEIII有时您一次不能打开超过 4 个表(除非更改一些 AUTOEXEC.BAT 参数并重新启动计算机,啊啊!...),对非规范化有一些兴趣。

但现在我看到这种解决方案类似于等待海啸给草坪浇水的园丁。请使用可用的喷壶(SQL 分析器)。

并且不要忘记,每次您对数据库的一部分进行非规范化时,您进一步适应它的能力就会降低,因为代码中的错误风险会增加,从而使整个系统越来越不可持续。

于 2008-10-03T11:08:27.177 回答
8

200 万行通常不是一个非常大的数据库,具体取决于您存储的信息类型。通常,当性能下降时,您应该验证您的索引策略。SQL Server 数据库引擎优化顾问可能会提供帮助。

于 2008-10-03T09:07:07.280 回答
3

可能有一百万个原因;使用 SQL Profiler 和 Query 分析器来确定您的查询为什么会变慢,然后再走“模式更改”之路。您需要做的就是创建几个索引并安排“更新统计信息”……但正如我所说,Profiler 和 Query Analyzer 是找出正在发生的事情的最佳工具。 .

于 2008-10-03T09:11:23.387 回答
1

我认为最好保持你的 OLTP 类型数据非规范化,以防止你的核心数据被“污染”。那会在路上咬你。

如果瓶颈是由于报告或只读需求,我个人认为除了规范化的“生产”表之外,非规范化报告表没有问题;创建一个流程以汇总到您需要使查询快速的任何级别。一个简单的 SP 或夜间进程,定期汇总和非规范化仅以只读方式使用的表,通常可以对用户体验产生巨大影响。

毕竟,如果没有人愿意使用您的系统,因为它太慢了,拥有一组理论上干净、完全规范化的数据有什么好处呢?

于 2009-04-26T14:34:37.383 回答
1

起初我们使用完全规范化的数据库,但现在由于性能问题(以减少连接),我们对其进行了部分规范化。

正如那句老话所说:“正常化,直到它受伤,非正常化,直到它起作用”。

在大型、重度使用的数据库中看到一定程度的非规范化以提高性能是很常见的,所以我现在不会太担心它,只要你的性能仍然是你想要的地方并且你的代码可以管理“非规范化”字段不会变得过于繁重。

当数据量变得非常大时,可能的解决方案是什么?未来客户增加?

对您的应用程序的域了解不多,很难说您如何应对未来的挑战,但是将最近使用的和旧的数据拆分到单独的表中是在高流量数据库中相当常见的方法 - 如果您的 95% 的用户是查询他们过去 30/45 天的数据,拥有一个“live_data”表,其中包含最近 60 天的数据,以及一个用于旧数据的“old_data”,可以帮助您提高性能。

一个好主意是确保您设置了广泛的性能监控,以便您可以在数据和负载增加时测量数据库的性能。如果您发现性能明显下降,可能是时候重新访问您的索引了!

于 2008-10-03T09:07:45.453 回答
1

那可能不是正确的决定。识别所有数据库交互并独立分析它们,然后找到有问题的交互并制定策略以最大限度地提高性能。同时打开数据库上的审计日志并挖掘它们可能会提供更好的优化点。

于 2008-10-03T09:07:52.273 回答
1
  • 首先确保您的数据库相当健康,如果可能,在其上运行 DBCC DBREINDEX,如果您无法承受性能损失,则运行 DBCC INDEXDEFRAG 并更新统计信息。

  • 以合理的采样时间运行 Profiler,足以捕获大多数典型功能,但过滤持续时间大于 10 秒的时间,你不关心只需要几毫秒的事情,甚至不看那些.

  • 现在您有了运行时间最长的查询,调整它们的鼻涕;获取出现最多的那些,查看查询分析器中的执行计划,花一些时间来理解它们,在必要的地方添加索引以加快检索速度

  • 查看创建覆盖索引;如果需要更改应用程序,如果它正在执行 SELECT * FROM... 当它只需要 SELECT LASTNAME, FIRSTNAME....

  • 重复分析器采样,持续时间为 5 秒、3 秒等,直到性能达到您的预期。

于 2008-10-04T00:32:56.623 回答
0

有趣...这里有很多答案..

rdbms / os 版本是 64 位的吗?

在我看来,性能下降了几倍。部分原因肯定是由于索引。您是否考虑过以与数据存储方式一致的方式对某些表进行分区?意思是,根据数据的输入方式(基于顺序)创建分区。由于大多数索引都是静态的,因此这将为您带来很多性能提升。

另一个问题是 xml 数据。你在使用 xml 索引吗?来自在线书籍 (2008) “使用主 XML 索引,支持以下类型的二级索引:PATH、VALUE 和 PROPERTY。”

最后,系统目前是否设计为运行/执行大量动态 sql?如果是这样,您将从记忆的角度出发,因为计划需要生成、重新生成并且很少重新执行。我称之为记忆搅动或记忆颠簸。

高温高压

于 2009-05-08T17:44:39.317 回答
0

在分析了索引和查询之后,您可能只想使用更多硬件。更多的公羊演出可能会奏效。

于 2008-10-04T19:28:58.937 回答
0

首先,正如许多其他人所说,几百万行并不大。我正在处理的当前应用程序有几个表,所有表都有超过一亿行,其中所有行都已标准化。

我们确实遇到了一些性能不佳的问题,但这是由于使用了默认的表统计设置造成的。相对于表的总大小插入少量记录,即将一百万条记录插入包含 100+ 百万条记录的表中不会导致表统计信息的自动更新,因此我们会得到表现不佳的查询计划作为生成的串行查询而不是并行查询。

至于非规范化是否是正确的决定,取决于您的架构。您是否必须定期执行深度查询,即大量连接以获取您经常需要访问的数据,如果是这样,那么部分去规范化可能是一种前进的方式。

但在 您检查索引和表统计策略之前不要这样做。
检查您是否使用了合理、结构良好的查询,并且您的联接格式正确。检查您的查询计划,您的查询实际上是按照您期望的方式解析的。

正如其他人所说,SQL Profiler/Database Engine Tuning Advisor 实际上做得很好。

对我来说,非规范化通常在我要做的事情列表的底部附近。

如果您仍然遇到问题,请检查您的服务器软件和硬件设置。

  • 您的数据库和日志文件是否使用不同的控制器在不同的物理磁盘上?
  • 它有足够的内存吗?
  • 日志文件是否设置为自动增长?如果是这样,自动增长限制是否会降低,即它是否经常增长。
于 2008-10-03T12:23:59.760 回答
0

我们一直尝试使用尽可能接近“现实世界”的数据库进行开发。这样你就可以避免很多像这样的陷阱,因为如果他的连接在调试过程中一直超时,任何老开发人员都会发疯。调试 Sql 性能问题 IMO 的最佳方法是 Mitch Wheat 建议的;profile 以查找有问题的脚本并从它们开始。优化脚本可以带您走得很远,然后您需要查看索引。还要确保你的 Sql Server 有足够的马力,尤其是 IO(磁盘)很重要。不要忘记;缓存为王。内存便宜;买多点。:)

于 2008-10-03T11:37:08.227 回答
0

你做任何有效的事都是对的。
...只要您意识到以后可能要付出代价。听起来你无论如何都在考虑这个问题。

检查事项:

死锁

  • 所有进程都以相同的顺序访问表吗?

缓慢

  • 是否有任何查询进行表扫描?
    • 检查大型连接(超过 4 个表)
    • 检查你的不足

请参阅我关于一般性能提示的其他帖子:

于 2008-10-03T13:50:57.167 回答
0

几百万条记录对于 SQL Server 来说是一个很小的数据库。它可以处理具有大量连接的 TB 级数据,毫不费力。您可能有设计问题或写得很糟糕的查询。

在您上线之前进行性能测试的荣誉。在您投入生产数月或数年之后,修复这些东西要困难得多。

你所做的可能是一个糟糕的选择。如果进行非规范化,则需要设置触发器以确保数据保持同步。是你做的吗?它增加了多少插入和更新时间?

我的第一个猜测是您没有在外键上放置索引。

关于可能出错的其他猜测包括过度使用以下内容:相关子查询标量函数视图调用视图游标 EAV 表缺乏 sargability 使用 select *

糟糕的表格设计也可能导致难以获得良好的性能。例如,如果您的表太宽,访问它们会变慢。如果您经常将数据转换为另一种数据类型以使用它,那么您将其存储不正确,这将始终对系统造成拖累。

动态 SQl 可能比存储过程更快,但可能不会。对于性能,这里没有一个正确的答案。对于内部安全性(您不必在表级别设置权限)和易于更改数据库,存储过程更好。

您需要运行探查器并确定最慢的查询是什么。还要查看所有经常运行的查询。每天运行数千次查询时,一个小小的改变就可以带来巨大的回报。

你还应该去买一些关于性能调优的书。这些将帮助您完成整个过程,因为性能问题可能是由于许多原因造成的:数据库设计、查询设计、硬件索引等。

没有一种快速修复方法,如果您不保持数据完整性,随机非规范化会给您带来更多麻烦。

于 2010-04-22T13:48:23.587 回答