请帮助解释我是否为了性能而破坏我的数据库架构:(

时间:2009-07-09 01:03:34

标签: sql-server database-design normalization denormalization

我在Sql 2008上有一个数据库正在生产近3年(之前是'05)。一直没问题,但效果不是很好。所以我正在调整架构和查询以帮助加速某些事情。此外,主表的分数每个表包含大约1-3个行(用于估算大小)。

这是一个示例数据库图表(Soz,在NDA下,所以我无法显示原文): -

alt text http://img11.imageshack.us/img11/4608/dbschemaexample.png

注意事项(与我的问题直接相关): -

  • 车辆可以有0(NULL)或1个无线电。 (左外连接)
  • 车辆可以有0(NULL)或1个Cupholder(左外连接)
  • 车辆有1个轮胎类型(内部连接)。

首先,这看起来像normalised database schema。我很糟糕和DB理论,所以我猜这是3NF(至少)...着名的遗言:)

现在,这会破坏我的数据库性能,因为这两个外连接和内连接被调用很多,并且在许多语句中还有一些连接。

要尝试修复此问题,我想我可能会尝试索引视图。创建视图是小菜一碟。但索引它,不起作用 - >无法使用连接或自引用表创建索引视图(另一个问题:()。

所以,我已经哭了几个小时(以及/wristsdyed hairwrote an emo song关于它并把它放在myfailspace上)并做了以下事情......

  1. 在每个“可选”外部联接表中添加了一个新行(在此示例中为Radios和CupHolders)。 ID = 0,其余数据='Unknown Blah'或0。
  2. 更新父表,以便任何NULL数据现在都为0。
  3. 更新从外部联接到内部联接的关系。
  4. 现在,这有效。我甚至可以制作索引视图,现在速度非常快。

    所以...我很痛苦。这恰好违背了我所教过的一切。我觉得很脏单独。感染。

    这是一件坏事吗?这是为了性能而对数据库进行非规范化的常见方案吗?

    我想对此有一些想法,请:)

    PS。随机谷歌发现的那些图像 - 所以不是我。

4 个答案:

答案 0 :(得分:2)

通常不在索引中使用空值。您所做的是提供一个标记值,以便该列始终具有允许更有效地使用索引的值。

您也没有更改数据库的结构,因此我不会将此称为非规范化。我已经用日期值完成了这个,你有一个“结束日期”null表示尚未结束。相反,我将其作为未来的已知日期方式,允许索引。

我认为这很好。

答案 1 :(得分:1)

数据库应始终设计并最初在3NF中实施。但是世界是一个现实的地方,而不是理想的地方,出于性能原因,可以恢复到2NF(甚至1NF)。不要嘲笑自己,实用主义总是在现实世界中击败教条主义。

如果您的解决方案能够提高性能,那么它就是一个很好的解决方案拥有一个真实的无线电(例如),由无人制造并且没有任何功能的想法并不是坏事 - 它之前已经完成了很多,相信我:-)你唯一的理由就是将该字段用作NULL是为了查看哪些车辆没有无线电,这些查询之间差别不大:

select Registration from vehicles where RadioId is null
select Registration from vehicles where RadioId = 0

我的第一个想法是简单地将四个表合并为一个并挂起重复的数据问题。 DBMS的大多数问题源于性能低下而不是低存储空间。

如果您当前的非规范化架构变得缓慢,也许将其保留为后备位置。

答案 2 :(得分:0)

“......所以我正在调整架构和查询,以帮助加速某些事情......” - 我会对此有所不同。看来你放慢了速度。 (开个玩笑。)

我喜欢Database Programmer博客。他有两个支持和反对规范化的列,你可能会觉得有用:

  1. http://database-programmer.blogspot.com/2008/10/argument-for-normalization.html
  2. http://database-programmer.blogspot.com/2008/10/argument-for-denormalization.html
  3. 我不是DBA,但我认为证据就在你面前:表现更差。我不明白将这些1:1的关系拆分成单独的表是什么让你买,但我很乐意接受指导。

    在我改变任何内容之前,我会要求SQL Server在每个查询速度很慢的情况下解析计划,并使用该信息来确切了解应该更改的内容。不要猜,因为正常化的大师告诉过你。获取数据以备份您正在执行的操作。您正在做的事情听起来像是在没有分析的情况下优化中间层代码。直觉感觉不太准确。

答案 3 :(得分:0)

我遇到了与绩效和学术成就相同的问题。我们有一个包含300列和91000条记录的客户数据库的大视图。我们使用外连接来创建视图,性能非常糟糕。我们已经考虑通过在我们连接的列(而不是null)上放入值为零的虚拟记录来更改为内部联接,以在视图上启用唯一索引。

我必须同意,如果表现很重要,有时候必须做出奇怪的事情才能实现。最终那些支付账单的人并不关心建筑是否完美。