作为软件开发人员和有抱负的 DBA,我在设计 SQL Server 数据库时尝试结合最佳实践(99% 的时间我的软件位于 SQL Server 之上)。我在开发之前和开发期间做出尽可能好的设计。
但是,就像任何其他软件开发人员一样,存在添加的功能、错误以及需要更改/创建数据库对象的需求更改。
我的问题是,查询调优应该主动还是被动?换句话说,在对代码/数据库进行大量修改后几周,我是否应该留出一天时间来检查查询性能并据此进行调整?即使它看起来运行正常?
或者我应该只知道低于平均水平的性能应该是数据库检查并返回众所周知的黑板?
查询调优可能会占用大量时间,而且根据初始数据库设计,它的收益可能微乎其微。我很好奇公认的作案手法。
两者都有,但主要是主动的
在开发过程中根据实际数据量和质量进行测试非常重要。在开发人员的 100 或 1000 行上运行查询然后在 1000 万个生产行上运行的查询持平,这是令人难以置信的常见情况。
它也允许您对“索引可能在这里有所帮助”做笔记。或者“重访我”。或者“将在下一个数据库版本中使用新功能 xxx 进行修复”。
但是,一些查询经不起时间的考验。数据分布发生变化或呈指数增长,因为优化器决定使用不同的连接类型。在这种情况下,您只能做出反应。
也就是说,至少对于 SQL Server,各种“缺失索引”和“最长查询”DMV 查询可以在电话呼叫之前指出问题区域
编辑:澄清...
主动并不意味着现在就调整每个查询。这意味着将您需要(经常运行)的内容调整到合理的响应时间。大多忽略每周凌晨 3 点的星期日报告查询。
好吧,我会咬住并采取逆势观点。首先,我会说你永远不应该从做你知道会给你带来麻烦的事情开始。如果您想将此称为应用最佳实践,请继续。这是就积极主动应该去的范围而言。
在那之后,时间(和金钱)就浪费了,所以继续努力并交付你的产品。与其花大量的设计时间调优查询(可能会或可能永远不会成为瓶颈),不如利用这段时间进行额外的测试,包括负载测试。
当您发现某些东西不符合您的设计规格时,或者如果某些东西落入分析器响应时间列表的底部 10% 或 20%,然后投入您需要的时间来调整它是什么破碎的。
在一个完美的世界中,一切都将从一开始就完美设计,并使用逻辑构建顺序进行开发。在现实世界中,预算和时间受到限制,您的测试数据可能最终看起来不像您的生产数据。出于这个原因,我说使用常识来主动避免问题,但集中你有限的资源来调整最终成为真正问题的事情,而不是花费你可能没有的时间和金钱来寻找想象中的或潜在的问题。
您将进行 3 种类型的调整,1 种是被动的,2 种是主动的。
反应性
出乎意料的是,某些查询开始给您带来问题。这可能是因为应用程序错误或功能、表增长超出预期、流量激增或查询优化器变得“有创意”。这可能是半夜 oh-crap-the-the-down 类型的事件,或者它可能是对非关键性的系统缓慢的响应。无论哪种方式,反应式调整的定义特征是你已经有问题了。不用说,您希望尽可能少地这样做。这让我们...
积极主动的
类型 1:日常维护
根据某种计划,每隔几个月或几周,这取决于您的架构更改频率和数据增长速度,您应该检查数据库性能分析工具的输出(例如,Oracle DBA 的 AWR 报告)。您正在寻找初期问题,即需要 Reactive 调整的问题,以及唾手可得的问题,这些问题不太可能很快导致问题,但可以通过不费吹灰之力进行改进,以期避免出现远- 未来的问题。你应该花多少时间在这上面将取决于你有多少时间,以及你可以花在什么上,但最佳数量永远不会为零。但是,您可以通过做更多的事情来轻松减少需要花费的金额……
类型 2:适当的设计
Knuth 对“过早优化”的警告广为人知并受到应有的尊重。但必须使用“过早”的正确定义。一些应用程序开发人员在被允许编写自己的查询时,倾向于采用他们遇到的第一个逻辑上正确的查询,而不管现在或将来的性能如何。或者他们可能会针对根本不代表生产环境的开发数据集进行测试(提示:不要这样做!开发人员应该始终能够访问真实数据以进行测试。)。关键是调优查询的适当时间是在它首次部署时,而不是在它出现在性能不佳的 SQL 列表中时,而且绝对不是在它导致严重问题时。
那么,在 DBA 领域,什么才算是过早的优化呢?我的首要任务是在没有明确需求的情况下牺牲规范化。当然,您可以在父行上维护总和,而不是在运行时从子行计算总和,但您真的需要这样做吗?如果你是 Twitter 或 Amazon,战略反规范化和预先计算可能是你最好的朋友。如果您正在为 5 个用户设计一个小的会计数据库,那么促进数据完整性的适当结构需要是重中之重。其他过早的优化同样是优先事项。不要花费数小时来调整每天运行一次并需要 10 秒的查询,即使您认为可以将其缩短到 0.1 秒。也许您有一份每天运行 6 小时的报告,但在投入时间对其进行调整之前,先探索将其安排为批处理作业。如果您的生产负载从未超过 10%(假设您可以管理安全性),请不要投资单独的实时复制报告实例。
通过针对实际数据进行测试,对增长和流量模式进行有根据的猜测(加上峰值允许),并应用您对平台优化器怪癖的了解,您可以部署(接近)优化运行的查询,不仅现在,而且将来,并且在不太理想的条件下。当您应用适当的技术时,可以准确地预测和优化查询性能(在每个组件都按照需要的速度运行的意义上)。
(当你在做的时候,学习统计学!)
在一个完美的世界中,所有调整都将在设计阶段主动完成,没有什么是被动的,但世界并不完美。你会发现测试数据有时不具有代表性,测试用例会被遗漏,负载会出乎意料地不同,并且会出现导致性能问题的错误。这些情况可能需要一些反应性调整,但这并不意味着反应性调整是首选。目标应该始终是预先抓住这些。
您的追溯调整计划非常务实。当您进行测试时,您应该记录预期的时间和吞吐量,并且有时应该实际构建分析,让您知道生产过程何时不符合设计规范。通过这种方式,您可以提前确定需要调整哪些代码。然后您不仅可以确定问题是什么,还可以确定为什么您没有在设计/测试阶段发现它。
对我来说,性能测试一直是开发过程的一部分。想要更改此表格、更改此报告、添加此功能?作为测试的一部分,您确保可以将个人和整体性能与已知基线和/或需求进行比较(例如,某些报告在后台运行或以其他方式自动化,因此性能 - 或者更确切地说是速度 - 每个查询中的每个查询系统并不总是最优先的)。
恕我直言,这根本不应该是一个反应过程——您永远不应该等到更改导致生产中的性能问题才开始对其做出反应。当您在开发/测试等方面进行更改时,您应该在具有相同应用程序和类似使用模式的类似硬件上使用类似数据测试这些更改。不要让这些更改仓促投入生产并让您大吃一惊。当不方便花一天的时间进行调整时,这几乎总是会发生 - 提前做好调整时间的预算。