我正在开发一个越来越受欢迎的移动网站,这导致一些关键数据库表的增长——我们在访问这些表时开始看到一些性能问题。我们不是数据库专家(现阶段也没有钱聘请任何人),我们正在努力了解导致性能问题的原因。我们的表不是那么大,所以 SQL Server 应该能够很好地处理它们,并且我们已经完成了我们在优化查询方面所做的一切。所以这是(伪)表结构:
[user] (approx. 40,000 rows, 37 cols):
id INT (pk)
content_group_id INT (fk)
[username] VARCHAR(20)
...
[content_group] (approx. 200,000 rows, 5 cols):
id INT (pk)
title VARCHAR(20)
...
[content] (approx. 1,000,000 rows, 12 cols):
id INT (pk)
content_group_id INT (fk)
content_type_id INT (fk)
content_sub_type_id INT (fk)
...
[content_type] (2 rows, 3 cols)
id INT (pk)
...
[content_sub_type] (8 rows, 3 cols)
id INT (pk)
content_type_id INT (fk)
...
我们预计这些行数会大幅增长(尤其是 user、content_group 和 content 表)。是的,用户表有很多列——我们已经确定了一些可以移动到其他表中的列。我们还对受影响的表应用了一堆索引,这些索引很有帮助。
最大的性能问题是我们用于搜索用户的存储过程(包括在 content_group_id 字段上连接到内容表)。我们尝试使用各种不同的方法来修改WHERE
andAND
子句,我们认为我们已经尽可能地完善了它们,但仍然太慢了。
我们尝试的另一件事没有帮助是在用户和内容表上放置一个索引视图。当我们这样做时没有明显的性能提升,所以我们放弃了这个想法,因为拥有视图层固有的额外复杂性。
那么,我们有哪些选择呢?我们可以想到一些,但都有优点和缺点:
表结构的非规范化
在用户表和内容表之间添加多个直接外键约束 - 因此每个内容子类型的内容表会有不同的外键。
优点:
- 通过使用其主键加入内容表将更加优化。
缺点:
- 我们现有的存储过程和网站代码会有很多变化。
- 维护多达 8 个额外的外键(更实际地,我们将只使用其中的 2 个)不会像当前的单个键那样容易。
表结构的更多非规范化
只需将我们需要的字段从内容表中直接复制到用户表中即可。
优点:
- 不再连接内容表 - 这大大减少了 SQL 必须做的工作。
缺点
- 同上:需要在用户表中维护的额外字段、对 SQL 和网站代码的更改。
创建中间层索引层
使用 Lucene.NET 之类的东西,我们会在数据库之上放置一个索引层。从理论上讲,这将提高所有搜索的性能,同时减少服务器上的负载。
优点:
- 这是一个很好的长期解决方案。Lucene 的存在是为了提高搜索引擎的性能。
缺点:
- 短期内会有更大的开发成本——我们需要尽快解决这个问题。
所以这些是我们想出的东西,在这个阶段,我们认为第二种选择是最好的——我知道非规范化有它的问题,但有时最好牺牲架构纯度以获得性能提升,所以我们准备支付这笔费用。
还有其他方法可能对我们有用吗?我上面概述的方法是否有任何其他优点和/或缺点可能会影响我们的决定?