数据库中的水平和垂直分区是什么?它们有何区别?

74

我看到过这样的说法:

SELECT 是关系表水平分割成两个元组集合。

PROJECT 是关系表垂直分割成两个关系表。

不过,我不理解这是什么意思。您能用通俗易懂的语言来解释一下吗?


在哪种数据库中?因为MySQL不包含“PROJECT”关键字。 - vallentin
4
这些术语在一般人理解的词汇中没有恰当的定义。维基百科关于关系代数的文章(http://en.wikipedia.org/wiki/Relational_algebra)用适合理解这些术语的语言对其进行了定义。 - High Performance Mark
5个回答

113

虽然不完全回答问题,但它回答了问题标题中所问的内容。因此,水平和垂直数据库分区的一般含义是:

水平分区将不同的行放入不同的表中。也许将邮政编码小于50000的客户存储在CustomersEast中,而将邮政编码大于或等于50000的客户存储在CustomersWest中。这两个分区表分别为CustomersEast和CustomersWest,而可以创建一个包含联合的视图来提供所有客户的完整视图。

垂直分区涉及创建具有较少列的表,并使用其他表来存储其余列。规范化也涉及跨表分割列,但垂直分割超越了这一点,即使已经进行了规范化,也会分割列。

此处查看更多细节。


2
这个答案更多地涉及到数据存储层面的分区,尽管他的问题似乎更多地涉及关系代数。概念上并没有太大的区别,只是为了明确这不是对原始问题的直接回答(尽管这也是我从标题中解释出来的方式)。 - Janick Bernet
是的,它只回答了问题标题。我在我的答案中更新了它,谢谢。 - Kuldeep Jain
我必须说@Stefan Steiger的答案比我的回答更详细地解释了分区:https://dev59.com/RGMl5IYBdhLWcg3wkXpx#38350155 - Kuldeep Jain
我在面试中无法回答这个问题,写了成千上万的查询,但我真的不知道这个问题的答案,他们肯定会通过这个问题来评估我的知识水平,哈哈。 - Aadam

24

死灵术。
我认为现有的答案过于抽象。

因此,这里是我对更实用解释的尝试:

从开发人员的角度来看,分区是关于性能的。
更确切地说,它涉及当您在表中拥有大量数据时,仍然希望快速查询数据时会发生什么。

这里是幻灯片的一些摘录,由Bill Karwin提供了关于水平分区的详细解释:

Horrible

上述内容不好,因为:

Problem 1

Problem 2

此外:

  • 您无法设置外键

  • 表结构不会保持同步

例如,在运行时:

ALTER TABLE BUGS_2009 ADD COLUMN hours NUMERIC;
  • 以前的表格中不包含新列
  • 不同的表格不能与UNION组合

解决方案: 水平分区

水平分区是一种必须由数据库引擎支持而不是应用程序的功能。该功能将数据库表格分成多个表格(使用某些标准 - 例如通常在列中具有不同值,例如示例表格“bugs”中的“year”列)。然后每个表格包含相同数量的列,但行数较少。

solution horizontal

区别:查询性能和简单性

Kirk Quote




现在,关于水平和垂直分区的区别:

“Tribbles”也可以在列中累积。 例如: Column Tribble

解决这个问题的方法是垂直分区

引用technet的话

垂直分区将表分割成包含较少列的多个表。垂直分区有两种类型:归一化和行拆分。归一化是从表中删除冗余列并将它们放入次要表中的标准数据库处理过程,这些次要表通过主键和外键关系链接到主表。行拆分将原始表垂直分成具有较少列的表。拆分表中的每个逻辑行与其他表中由唯一键列标识的同一逻辑行匹配。例如,从每个拆分表中连接ID为712的行可重新创建原始行。像水平分区一样,垂直分区可以让查询扫描更少的数据,从而提高查询性能。例如,包含七列但通常只引用前四列的表可能受益于将最后三列拆分成单独的表。应仔细考虑垂直分区,因为分析来自多个分区的数据需要连接表的查询。如果分区非常大,垂直分区也可能影响性能。
此外,可以将大型列(例如大二进制对象)或很少使用的列添加到辅助表中,建立1:1的关系。
将这些列移出主表可显著提高查询时间。
以上就是总结。

Proper normalization

现在是关于SELECT vs. PROJECT:

这篇Stack Overflow的帖子描述了它们之间的区别:

Select操作:此操作用于从指定给定逻辑的表(关系)中选择行,该逻辑称为 谓词。谓词是用户定义的条件,用于选择用户所选的行。

Project操作:如果用户只对选择少数属性的值感兴趣,而不是选择所有属性的值 表(关系),那么应该使用PROJECT操作。

SELECT是一个实际的SQL操作(语句),而PROJECT是关系代数中使用的术语。

从您在Stack Overflow上发布此内容而不是在MathOverflow上发布来看,我建议您如果只想学习用于开发应用程序的SQL,则不要阅读关系代数书籍。

如果您迫切需要一本关于(高级)SQL的书籍推荐,这里有一本。

SQL反模式:避免数据库编程陷阱
作者:比尔·卡温
ISBN-13:978-1934356555
ISBN-10:1934356557

这是唯一值得一读的关于SQL的书。
我看到的大多数其他关于SQL的书都可以用这句关于Photoshop书的玩世不恭的话来概括:

关于Photoshop的书比使用Photoshop的人还多。


3
这一定是问题的正确答案。我们并不希望去StackOverflow只是为了重新阅读维基百科中的所有内容。 - pexea12
1
这不是问题的被选答案真是太不应该了。 - egremont of yorke

24

投影操作会在关系中创建一组属性的子集,因此称为“竖向分割”。

选择操作会在关系中创建元组的子集,因此称为“水平分割”。

假设有一个表(r),如下所示:

a : b : c : d : e
-----------------
1 : 2 : 3 : 4 : 5
1 : 2 : 3 : 4 : 5
2 : 2 : 3 : 4 : 5
2 : 2 : 3 : 4 : 5

这样的表达:

PROJECT a, b (SELECT a=1 (r))

-- SELECT a, b FROM r WHERE a=1

会"做"

a : b | c : d : e
-----------------
1 : 2 | 3 : 4 : 5
1 : 2 | 3 : 4 : 5
=================    <  -- horizontal partition (by SELECTION)
2 : 2 | 3 : 4 : 5
2 : 2 | 3 : 4 : 5

      ^  -- vertical partition (by PROJECTION)

导致

a : b
------
1 : 2 
1 : 2 

3
水平和垂直的区别来自于传统的数据库表格视图。数据库可以进行垂直分割,将不同的表和列存储在单独的数据库中,或者进行水平分割,将同一表的行存储在多个数据库节点中。

enter image description here

水平分区通常被称为数据库分片
# Example of vertical partitioning
fetch_user_data(user_id) -> db[“USER”].fetch(user_id)
fetch_photo(photo_id) ->    db[“PHOTO”].fetch(photo_id)
# Example of horizontal partitioning
fetch_user_data(user_id) -> user_db[user_id % 2].fetch(user_id)

在这里查看更多详细信息:https://medium.com/@jeeyoungk/how-sharding-works-b4dec46b3f6


1
考虑数据库中的一个单独表格,它有一些行和列。
有两种方法可以选择数据:您可以选择某些行,或者您可以选择某些列(好吧,三种方法,您可以选择某些行,并在其中选择某些列)。
您可以将选择视为选择某些行-这是水平的(不选择其余部分,因此进行分区)
您可以将投影视为选择某些列-这是垂直的(不选择其余部分)

我会点赞这个答案,但问题中提到的“水平”和“垂直”术语从未被提及,我认为并不是每个人都明白选择行是水平分区,选择列是垂直分区。 - Janick Bernet
大多数行都是水平的,不是吗? :-) 无论如何,为了明确起见,我添加了额外的内容。 - djna

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接