我有db denormalization的设计问题 我正在建立一个相对较大的数据库,需要尽可能地优化它。
这是一个非常简化的问题模型 图片中的所有表都是链接的,并且使用规范化的数据库来获取来自特定国家/地区的所有用户,我必须加入所有表。那是cca 250个国家x cca 12000个城市x cca 625000个地区x?地址x?用户......简而言之,这需要很长时间才能加入。
我想要做的是在country_id
表中使user
多余,这样我就可以在没有任何加入的情况下获得相同的查询。
问题是,在这种模型中保持一致性的最佳做法是什么(顺便说一句,使用MySql)?
一种方法,也许最快的方法是在插入/更新/删除数据时确保应用程序级别的一致性。
其他是存储过程,我真的看不出任何优点。只有直接调用它们才能确保一致性。如果您想在没有程序的情况下进行一些更改,则一致性会中断。
我一直在关注触发器...不确定如何实现它,以及我将在性能上获得多少。
无论如何,最好确保数据库级别的一致性。
有什么建议吗?
答案 0 :(得分:6)
图片中的所有表格都是链接的,并带有规范化 例如,获取来自特定国家/地区的所有用户的数据库 必须加入所有表格。
您必须加入所有表,因为您使用代理键(ID号),而不是因为表是“规范化”的。使用id号等代理键与规范化无关。
自然键和外键约束是解决问题所需的全部内容。
了解其工作原理的最简单方法是从完整数据开始,然后完全向后工作。假设所有数据都是正确的。
addr_id street street_num region city country
--
1 Babukiaeeva 3a 10000 Zagreb Croatia
2 Riva 16 51000 Rijeka Croatia
3 Andrije Hebranga 2-4 10000 Zagreb Croatia
4 Andrijeviaeeva 2 110000 Zagreb Croatia
要记录“地区'10000'与”克罗地亚“国家/地区'萨格勒布'相关联的事实,请创建一个新表格,并从此查询中填充该表格。
SELECT DISTINCT region, city, country from addresses;
表格如下所示。
Table: regions
Primary key: {region, city, country}
region city country
--
10000 Zagreb Croatia
51000 Rijeka Croatia
110000 Zagreb Croatia
然后设置外键引用。
ALTER TABLE addresses
ADD CONSTRAINT FOREIGN KEY (region, city, country)
REFERENCES regions (region, city, country);
要记录“城市'萨格勒布'在国家'克罗地亚'中的事实”,请创建一个新表格,从此查询中填充。
SELECT DISTINCT city, country from regions;
表格如下所示。
Table: cities
Primary key: {city, country}
city country
--
Zagreb Croatia
Rijeka Croatia
然后设置外键引用。
ALTER TABLE regions
ADD CONSTRAINT FOREIGN KEY (city, country)
REFERENCES cities (city, country);
对国家重复。表格国家,城市和地区都是关键,所以他们在5NF。 (它们不能具有任何非关键依赖关系,因为它们没有非关键列。)在大区域的上下文中,与整个欧洲一样,地址表也可能是5NF。
它的查询性能条款很可能围绕当前架构运行,因为它不需要连接。
您可能想要使用ON UPDATE CASCADE
;但是,你可能不想要级联删除。
答案 1 :(得分:1)
首先 - 它真的太慢了吗? 你试过吗? 你有一个转储所有用户的应用程序(为什么?),或者你偶尔提取一个/少数用户。由于您在所有这些ID上都有主键,因此检索速度不应该那么慢,毕竟背景中有B树。
其次,我不会在街道数字级别上进行标准化,你很难从中获益,而且你可能最终会在用户和用户之间建立一个近乎1:1的关系。一个地址。因此,将您的街道号码移动到客户端,或者您甚至可以将整个地址表移动到用户。我可能会将区域表也移动到客户端(这些是城市区域?)并最终得到用户,城市和国家/地区表。
然后你有两个连接,如果仍然太慢,你可以在用户中放置多余的国家/地区密钥(或者,因为我们正在进行非规范化 - 国家/地区名称)。我将使用触发器来保持完整性,更准确地说,您必须编写:插入和更新触发器(更新只需在regionId / cityId更改时触发),以及国家/地区的更新触发器(如果如果国家/地区的名称发生变化,您可以在用户表中使用国家/地区名称。
性能方面,你不会获得,但会失败,但是我认为用户表上的插入和更新不是那么频繁,你根本就没有注意到它。
最后,由于您没有详细解释您(web?)应用程序的性质和大小,只需提醒您,您可能还需要考虑/包含关系数据库之外的其他优化技术(缓存,no-sql) dbs等。)。
答案 2 :(得分:0)
假设您没有尝试对所有数据进行反规范化,那么加入并不是很多。
另一方面,大多数人只有一个地址表,或者(喘息!)将地址信息保存在用户表中。您期望支持多少个国家/城市,与多少用户相比?