我希望select
检索person
并进一步进行一些插入,删除和更新。
如果我想要person
生成Brazil
,那么最佳方法是什么?
在表格city
中制作2个外键country
和person
:
Person(id, name, profession, **id_country**, **id_city**)
cities (id, city, **id_country**)
countries (id, country)
或表cities
中仅person
的一个外键和表county
中的其他外键cities
Person(id, name, profession, **id_city**)
cities (id, city, **id_country**)
countries (id, country)
或像第一个选项一样查看?
对于插入,删除和更新数据,它们仍然是最好的表吗?性能没有差异?我也很困惑,什么会影响架构中的性能?
答案 0 :(得分:2)
一般来说,数据完整性比性能更重要,因此只有在代表性数据量上执行了度量时,才会对 1 进行非规范化。结果表明对更好性能的强烈需求。更常见的情况是,规范化架构的表现会很好,特别是如果你的物理设计正确(例如索引)。
在这种特殊情况下,我的预感是第二种(标准化)设计可以正常工作。
话虽如此,可能是查询的最有效设计:"哪些人住在特定国家"看起来像这样:
然后{P} PK上的cluster。这样,属于同一COUNTRY_ID的所有人在数据库中以物理关闭存储在一起,大大减少了 2 上方查询的I / O.
另一方面,您不再使用简单的自动增量机制来生成CITY_NO和PERSON_NO,PERSON上的二级索引很昂贵,因为群集导致其他查询变慢等等。所以,这不是绝对的"更好"比你的第二个设计,他们只是有不同的优点/缺点,你必须决定在你的特定情况下哪个更好的权衡。
1 这会阻止数据库自我防卫"本身就是糟糕的数据。在您的情况下,第一个(非规范化)设计将允许一个人引用一个不包含同一个人引用的城市的国家。
2 I / O往往是大多数查询的最大成本。
答案 1 :(得分:1)
取决于您想要实现的目标。在这两种情况下,您都要输入冗余数据。它被称为非规范化。非规范化的第二个例子称为"短路键":
Person(id, name, profession, **id_city**)
cities (id, city, **id_country**)
countries (id, country)
执行查询时,结果会产生更少的表连接。第一个例子被称为"星型模式":
Person(id, name, profession, **id_country**, **id_city**)
cities (id, city, **id_country**)
countries (id, country)
星型模式由一个或多个引用任意数量的维度表的事实表组成。星型模式连接逻辑通常比从高度规范化的事务模式中检索数据所需的连接逻辑更简单。这个例子通常出现在数据仓库数据库设计中。
在任何情况下都不会影响性能,您可以选择其中一个来检索所需的数据。
答案 2 :(得分:1)
(你的原始帖子并没有解决性能问题,而是规范化,但是它有很多编辑,并且"性能"被引入,可能是因为你的评论提到了它。)
关系模型的点之一是通过自动优化实现自动化实现的通用查询。 最初忽略性能。只需做一个简单的设计。(在此之前你必须学习如何制作一个。)Ids与性能无关。规范化与性能有关,但是因为你应该首先将其标准化为5NF,这是没有实际意义的。外键与性能有关,但由于您应该为完整性定义它们,因此它们在性能方面的作用没有实际意义。适当的设计可以在以后进行调整。
无论如何,表现是一个因素的权衡,如果你不知道你想做什么样的事情,讨论表现是没有意义的。 (或者,如果你甚至不知道那些东西是什么。)此外,必须衡量与绩效相关的属性,甚至认为手动优化干预是合适的。 (而且你必须要了解那些因素甚至是什么。)
当性能成为一个已证明的问题,因为特定的应用程序会生成特定的查询或更新模式,那么您可以解决性能问题。首先通过索引和视图使这些模式表现更好 - 总是以牺牲其他模式为代价。
您提及(并且未提及)的各种事物以及您提及它们的方式表明您对性能的误解及其与设计的关系。您对关系结构,查询和DBMS的理解也非常低。在您了解有关基本设计的更多知识之前任何有关性能偏差的建议都是错误的。所以忘掉性能吧。 对性能产生负面影响的主要因素是对性能的过早关注妨碍了简单的设计。
最简单的设计是
person(id, name, profession, city, country)
-- person [id] is named [name] and practises [profession] in [city], [country]
city (name, country) -- [name] uniquely names a city within country [country]
country (name) -- [name] uniquely names a country
这有一些键和FK,只是声明它们 - 这与性能无关。它在5NF。
您可能会明白,以下设计(您可以添加相关约束)对您来说可能比前一个更好 - 这与性能无关。然后你可以转移到它并将之前的表作为视图提供给老用户 - 这与性能无关。
person(id, name, profession, id_city)
-- person [id] is named [name] and practises [profession] in [id_city]
city (id, name, id_country) -- city [id] is named [name] and is in country [id_country]
country (id, name) -- country [id] is named [name]
这里的id_country会违反5NF,因为它在功能上依赖于非密钥id_city。
答案 3 :(得分:1)
这个问题与你们所做的那个问题非常相似:
Create many tables or just one
答案也很相似 - 这取决于你想要达到的目标。这两种解决方案都可行,并且都有利弊,应该根据具体情况进行一些权衡分析 。在这种情况下,你无法回答你的问题。
我在两个版本中看到的唯一区别是Person表中的外键id_country:
人(身份证,姓名,职业,**** id_country ****,id_city)
城市(id,city,id_country)
国家(身份证,国家)
问题是“我们需要它吗?”
所以,这两种解决方案的优缺点是:
<强> 1。解决方案:使用id_contry:
<强> 2。解决方案:没有id_country:
因此,第一个解决方案有效地为您提供了更简单的查询结构和更好的性能,可以按国家/地区检索人员(您想要的),但它有其成本(参见优缺点)。另一方面,务实的思考认为,国家 - 城市数据非常稳定,而且经常不会改变,这一事实有利于第一种解决方案。
如果这种非规范化和轻微出现不一致的可能性,你可以采取第一种解决方案。