我想参与一个项目,但这有点奇怪。我想创建一个显示歌词及其翻译的网站,但它们是并排显示的(所以这不仅仅是网站的正常版本)。
我已经像这样对表进行了规范化(格式化为显示层次结构)。
artists
artistNames
albums
albumNames
tracks
trackNames
trackLyrics
user
所以问题,
首先,这将是一个惊人的七连接。我过去一定写过很小的问题,因为我从未遇到过这样的问题。加入这么多桌子是件坏事吗?我很确定我会在这个项目中使用SQLite,但有人认为PostgreSQL或MySQL可以通过这样一个非常大的连接来表现更好吗?
第二,我目前的自建框架使用数据映射器来创建域对象。这是我第一次使用这么多的一对多关系,所以我的mapper实际上只占一行作为一个对象。例如,
id name
------ ----------
1 Jackie Chan
2 Stephen Chow
因此,映射对象非常容易。但是那些一对多的关系......
id language name
------ ---------- -------
1 en Jackie Chan
1 zh 陳港生
2 en Stephen Chow
2 zh 周星馳
......我不知道该怎么做。循环遍历结果集以创建一个海量数组并将其提供给我的域对象工厂是处理这样的数据集的唯一选择吗?
<?php
array(
array(
'id' => 1,
'names' => array(
'en' => 'Jackie Chan'
'zh' => '陳港生'
)
),
array(
'id' => 2,
'names' => array(
'en' => 'Stephan Chow',
'zh' => '周星馳'
)
)
);
?>
我只是对这些表进行非规范化处理,所以我可以让每个对象应用程序运行一行,但我总是读到这不是可行的方法。
第三次,这个架构是否适合这项工作?
答案 0 :(得分:3)
请注意。我不太确定7个表是一个很大的连接。我似乎记得Postgres有一个特殊的查询优化器(基于遗传算法,不能少)只有在你加入12个或更多表后才会启动。
答案 1 :(得分:3)
一般规则是使架构尽可能规范化。然后使用预期的数据量执行压力测试。如果发现性能瓶颈,应尝试按以下顺序进行优化:
通常只有在处理“大量”数据时才需要使用非规范化数据库。我在互联网上检查了几个歌词数据库,我发现最大的歌词有大约400,000首歌曲。假设您可以找到由500,000名艺术家执行的1.000.000的歌词。这是所有数据库可以在普通现代计算机上轻松处理的数据量。
答案 2 :(得分:3)
在严肃的工业工作中,十二路加入并非闻所未闻。您需要足够的硬件,强大的DBMS和良好的数据库设计。对于任何良好的环境,七路连接应该是轻而易举的。
根据需要分离数据,以避免数据库更新异常等问题。当您不遵循规范化规则时,您会获得这些异常。您可以根据需要连接数据,以便在单个结果中获取所需的数据。
有时,在构建数据库时忽略一些规范化规则会更好。在这种情况下,您需要一套替代设计原则,以避免通过反复试验进行设计。您正在进行的连接数量与循环结果或元组和对象之间的不幸映射的缺点几乎没有关系。
元组(表行)和对象之间的大多数映射都以不正确的方式完成。元组是一个对象,但它不是面向应用程序的对象。这可能导致性能问题或难以编程或两者兼而有之。
就你可以避免它而言,不要一次一行地循环结果。将结果作为一组数据处理。如果你不能用PHP做到这一点,那么你需要学习如何,或者获得更好的编程环境。
答案 3 :(得分:2)
这样做很多连接不应该是任何严重数据库的问题。我没有和SQLite合作过,知道它是否属于“严重”类别。找出答案的唯一方法是创建架构,加载大量数据并开始查看查询计划(视觉解释在这里非常有用)。当我进行这些测试时,我通常会拍摄10倍于我期望的制作数据。如果这些数据的工作正常,我知道我应该对实际数据没问题。
此外,根据您需要检索数据的方式,您可能希望尝试子查询而不是连接:
select a.*, (select r.name from artist r where r.id=a.artist a and r.locale='en') from album where a.id=1;
答案 4 :(得分:0)
我帮助一位朋友优化了网店。在你的情况下,它是相同的。
首先。您的优先级,网页速度或更新速度是多少?
普通表单旨在简化数据维护。如果Prince再次改名,瞧,只有一行更新。但是如果你想让你的网页尽可能快地渲染,那么第3次正常就不是你最好的计划了。是的,每一个都是正确的,它会做7路加入没问题,但那将是几十个i / o的...索引查找每个表然后表访问rowid,然后一次又一次。如果您对网页加载速度进行非规范化,则可以执行2或3次i / o。这也将允许更大的扩展,因为每个页面命中将需要更少的i / o来完成,你将能够在最大化你的i / o之前做更多的同时命中。
但是没有理由不这两个。您可以保留基本数据,正式形式的正式副本,然后编写一个脚本,可以为Web性能生成非正常表。如果它不是那么大,你可以在几分钟的维护停机时间内重新生成整个东西。如果它非常大,您可能需要对更新有所了解,并且只需要更改需要在中间驱动表中保留更改向量的内容。
但是你的设计核心我有一个问题。
艺术家名称随时间而变化。 John Cougar成为John Cougar Melonhead(或其他什么),后来他成为John Mellancamp。你关心约翰做了哪首歌吗?你会用和来自有效日期标记条目吗?
看起来你有一个从艺术家到专辑的1-n关系,但真的应该有很多人。
有时相同的专辑会不止一次发行,包含不同的曲目,有时曲目的名称也不同。想想国际版本。或奖金曲目。你怎么知道这张专辑都是一样的?
如果您不关心这些细节,那么为什么还要理想化呢?如果Jon和Vangelis是一位艺术家,那么就没有必要进行规范化。你对标准化提供的答案不感兴趣。