【问题标题】:Handling large databases处理大型数据库
【发布时间】:2010-09-15 00:39:11
【问题描述】:

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

我想补充一点:

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

【问题讨论】:

  • @Mitch,也许他们都不适合他 :)
  • @Joe Phillips:那么也许他们问错了问题......

标签: sql-server database performance database-design query-optimization


【解决方案1】:

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

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

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

我会在这里勉强出去(因为通常都是这种情况),但如果你的问题也不是,我会感到惊讶

  1. 缺少用于代价高昂查询的“正确”覆盖索引
  2. 配置不当或在指定的磁盘子系统下

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

【讨论】:

  • 话从我嘴里说出来!您所描述的闻起来像磁盘 I/O 问题。当更多用户在系统上矿石时,问题会变得更糟吗?
【解决方案2】:

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

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

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

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

【讨论】:

  • +1 同意 - 在使用现代数据库引擎时,很少有理由进行非规范化。事实上只有一个:性能,你应该证明表结构是原因,而不是假设它
【解决方案3】:

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

【讨论】:

    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

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

      【讨论】:

        【解决方案6】:

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

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

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

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

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

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

        【讨论】:

          【解决方案7】:
          • 首先确保您的数据库相当健康,如果可能,在其上运行 DBCC DBREINDEX,如果您无法承受性能损失,则运行 DBCC INDEXDEFRAG 并更新统计信息。

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

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

          • 看看创建覆盖索引;如果它只需要 SELECT LASTNAME, FIRSTNAME....

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

          【讨论】:

            【解决方案8】:

            我认为最好将您的 OLTP 类型数据保持非规范化,以防止您的核心数据受到“污染”。这会让你大吃一惊。

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

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

            【讨论】:

              【解决方案9】:

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

              【讨论】:

                【解决方案10】:

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

                检查事项:

                死锁

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

                缓慢

                • 是否有任何查询在执行表扫描?
                  • 检查大型联接(超过 4 个表)
                  • 检查您的成绩

                查看我关于一般性能提示的其他帖子:

                【讨论】:

                  【解决方案11】:

                  在分析完索引和查询之后,您可能需要更多的硬件。再多几场 ram 就可以了。

                  【讨论】:

                    【解决方案12】:

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

                    rdbms/os 版本是 64 位的吗?

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

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

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

                    HTH

                    【讨论】:

                      【解决方案13】:

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

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

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

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

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

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

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

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

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

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

                      【讨论】:

                        【解决方案14】:

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

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

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

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

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

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

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

                        • 您的数据库和日志文件是否已打开 使用单独的物理磁盘 单独的控制器?
                        • 是否有 足够的内存?
                        • 是否设置了日志文件 自动生长?如果是这样,自动增长 限制到低,即它是否增长到 经常。

                        【讨论】:

                          猜你喜欢
                          • 1970-01-01
                          • 1970-01-01
                          • 2010-09-24
                          • 1970-01-01
                          • 1970-01-01
                          • 2023-04-02
                          • 1970-01-01
                          • 2022-01-06
                          相关资源
                          最近更新 更多