在我正在处理的一个Web应用程序中,所有的数据库操作都使用在Entity Framework ORM上定义的一些通用存储库来抽象。
但是,为了对通用存储库进行简单设计,所有涉及的表都必须定义一个唯一的整数(Int32
在C#中,int
在SQL中)。到目前为止,这始终是表格的PK以及IDENTITY
。
外键被大量使用,它们引用这些整数列。它们是一致性和ORM生成导航属性所必需的。
应用程序层通常执行以下操作:
- 从表(*)加载初始数据 -
SELECT * FROM table
- 更新 -
UPDATE table SET Col1 = Val1 WHERE Id = IdVal
- 删除 -
DELETE FROM table WHERE Id = IdVal
- 插入 -
INSERT INTO table (cols) VALUES (...)
不太频繁的操作:
- 批量插入 -
BULK INSERT ... into table
所有数据加载后跟(*)(以检索生成的标识符) - 批量删除 -这是正常的删除操作,但是从ORM的角度来看,这是“笨拙的”:
DELETE FROM table where OtherThanIdCol = SomeValue
- 批量更新 -这是正常的更新操作,但从ORM的角度来看是“庞大”的:
UPDATE table SET SomeCol = SomeVal WHERE OtherThanIdCol = OtherValue
*所有小表都缓存在应用程序级别,几乎所有小表都SELECTs
不会到达数据库。典型的模式是初始载荷和大量INSERT
s,UPDATE
s和DELETE
s。
根据当前应用程序的使用情况,在任何表中达到100M条记录的可能性很小。
问: 从DBA的角度来看,由于存在此表设计限制,我是否会遇到重大问题?
[编辑]
在阅读了答案(感谢您的宝贵反馈)和参考文章之后,我觉得我必须添加更多详细信息:
当前应用程序的详细信息 -我没有提及当前的Web应用程序,因为我想了解该模型是否也可以用于其他应用程序。但是,我的特殊情况是从DWH中提取大量元数据的应用程序。源数据非常混乱(以一种奇怪的方式进行了归一化,存在一些不一致,在许多情况下没有自然的标识符等),并且我的应用程序正在生成清晰的分离实体。另外,还会显示许多生成的标识符(
IDENTITY
),以便用户将其用作业务密钥。除了进行大量代码重构外,这还不包括GUID的使用。“它们不应该是唯一标识行的唯一方法”(Aaron Bertrand♦)-这是一个非常好的建议。我所有的表还定义了UNIQUE CONSTRAINT,以确保不允许业务重复。
前端应用程序驱动的设计与数据库驱动的设计 -设计选择是由这些因素引起的
实体框架限制 -允许多列PK,但其值无法更新
自定义限制 -具有单个整数键可以大大简化数据结构和非SQL代码。例如:所有值列表都有一个整数键和一个显示的值。更重要的是,它保证任何标记为缓存的表都可以放入
Unique int key -> value
映射中。
复杂的选择查询 -这几乎永远不会发生,因为所有小的(<20-30K记录)表数据都在应用程序级别缓存。这使编写应用程序代码时的工作变得更加艰难(更难于编写LINQ),但是数据库命中了更好的情况:
列表视图 -不会
SELECT
在加载时生成查询(缓存所有内容)或类似以下查询:SELECT allcolumns FROM BigTable WHERE filter1 IN (val1, val2) AND filter2 IN (val11, val12)
所有其他必需的值都是通过缓存查找(O(1))获取的,因此不会生成复杂的查询。
编辑视图 -将生成如下
SELECT
语句:SELECT allcolumns FROM BigTable WHERE PKId = value1
(所有过滤器和值均为int
s)