是否有理由担心表中的列顺序?

lyn*_*ynn 79 mysql sql database-table

我知道你可以用FIRST和AFTER改变MySQL中的列顺序,但为什么你要打扰?由于好的查询在插入数据时明确地命名列,是否真的有理由关心列中的列的顺序?

And*_*mar 91

列顺序对我调整过的一些数据库有很大的性能影响,包括Sql Server,Oracle和MySQL.这篇文章有很好的经验法则:

  • 首先是主键列
  • 接下来是外键列.
  • 接下来经常搜索的列
  • 以后经常更新的列
  • Nullable列最后.
  • 在更频繁使用的可空列之后最少使用可空列

性能差异的一个示例是索引查找.数据库引擎根据索引中的某些条件查找行,并返回行地址.现在说你正在寻找SomeValue,它在这个表中:

 SomeId int,
 SomeString varchar(100),
 SomeValue int
Run Code Online (Sandbox Code Playgroud)

引擎必须猜测SomeValue的起始位置,因为SomeString的长度未知.但是,如果您将订单更改为:

 SomeId int,
 SomeValue int,
 SomeString varchar(100)
Run Code Online (Sandbox Code Playgroud)

现在引擎知道在行开始后可以找到SomeValue 4个字节.因此,列顺序可能会产生相当大的性能影响.

编辑:Sql Server 2005在行的开头存储固定长度的字段.每行都有一个varchar开头的引用.这完全否定了我上面列出的效果.因此,对于最近的数据库,列顺序不再有任何影响.

  • 此答案中的URL不再有效,是否有人有替代? (6认同)
  • @TopBanana:不是varchars,这是将它们分散到普通char列的原因. (4认同)
  • @TopBanana:不确定你是否认识Oracle,但它没有为VARCHAR2(100)保留100个字节 (4认同)

Qua*_*noi 41

更新:

MySQL,可能有理由这样做.

由于变量数据类型(如VARCHAR)以可变长度存储InnoDB,因此数据库引擎应遍历每行中的所有先前列以找出给定数据的偏移量.

对于柱子,影响可能高达17%20.

有关详细信息,请参阅我的博客中的此条目:

Oracle,尾随NULL列不占用空间,这就是为什么你应该总是将它们放在表的末尾.

同样在内Oracle和中SQL Server,在大行的情况下,ROW CHAINING可能发生.

ROW CHANING 正在拆分一个不适合一个块的行,并将其跨越多个块,并与链接列表相连.

读取不适合第一个块的尾随列将需要遍历链表,这将导致额外的I/O操作.

请参阅此页为插图ROW CHAININGOracle:

这就是为什么你应该将经常使用的列放在表的开头,将经常不使用的列或倾向于使用的列放到NULL表的末尾.

重要的提示:

如果您喜欢这个答案并想投票,请投票给@Andomar我答案.

他回答了同样的事情,但似乎无缘无故地被投票.


ara*_*nid 6

在上一次工作的Oracle培训期间,我们的DBA建议将所有非可空列放在可空的列之前是有利的......尽管TBH我不记得原因的细节.或者也许只是那些可能会更新的应该到最后?(如果扩展,可能会推迟行)

一般来说,它不应该有任何区别.正如您所说,查询应始终指定列本身,而不是依赖于"select*"的排序.我不知道有任何DB允许它们被更改......好吧,我不知道MySQL允许它直到你提到它.

  • 他是对的,Oracle不会将尾随的NULL列写入磁盘,从而节省了一些字节.请参见http://www.dba-oracle.com/oracle_tips_ault_nulls_values.htm (4认同)

mar*_*c_s 5

不,SQL数据库表中列的顺序完全不相关 - 除了显示/打印目的.重新排序列没有意义 - 大多数系统甚至没有提供这样做的方法(除了删除旧表并使用新的列顺序重新创建它).

编辑:从关系数据库的维基百科条目,这里的相关部分,我清楚地表明,列顺序永远不应该是关注:

关系被定义为一组n元组.在数学和关系数据库模型中,集合是一个无序的项集合,尽管有些DBMS对其数据强加了一个顺序.在数学中,元组有一个顺序,并允许重复.EF Codd最初使用这个数学定义定义了元组.后来,它是EF Codd的一个很好的见解,即使用属性名称而不是排序将在基于关系的计算机语言中更加方便(通常).这种洞察力至今仍在使用.

  • 除非您关心性能*,否则RDBMS不依赖于表排序*.不同的实现将对列的顺序具有不同的性能损失.它可能很大,也可能很小,这取决于实施.元组是理论上的,RDBMS是实用的. (5认同)
  • -1.我用过的所有关系数据库都在某种程度上有列排序.如果从表中选择*,则不会以随机顺序返回列.现在,磁盘与显示器是一个不同的争论.并引用数学理论来支持关于数据库实际实现的假设只是无稽之谈. (3认同)

Chr*_*isF 5

当您必须键入时输出的可读性:

select * from <table>
Run Code Online (Sandbox Code Playgroud)

在你的数据库管理软件中?

这是一个非常虚假的理由,但目前我想不出其他的理由。


Cra*_*ker 5

一些写得不好的应用程序可能依赖于列顺序/索引而不是列名.他们不应该,但确实发生了.更改列的顺序会破坏此类应用程序.

  • 应用程序开发人员使他们的代码依赖于表DESERVE中的列顺序来破坏他们的应用程序.但是应用程序的用户不值得中断. (2认同)

Hol*_*ger 5

2002 年,Bill Thorsteinson 在 Hewlett Packard 论坛上发布了他通过重新排序列来优化 MySQL 查询的建议。此后,他的帖子在互联网上被复制粘贴了至少一百次,而且往往没有引用。准确地引用他的话...

\n
\n

一般经验法则:

\n
    \n
  • 首先是主键列。
  • \n
  • 接下来是外键列。
  • \n
  • 接下来是经常搜索的列。
  • \n
  • 以后经常更新专栏。
  • \n
  • 最后是可为空的列。
  • \n
  • 最少使用的可为空列位于最常用的可为空列之后。
  • \n
  • 自己的表中的 Blob 几乎没有其他列。
  • \n
\n
\n

资料来源:惠普论坛。

\n

但那篇文章是在 2002 年发布的! 这个建议是针对 MySQL 3.23 版本的,比 MySQL 5.1 发布早了六年多。 并且没有任何参考文献或引文。那么,比尔是对的吗?那么这个级别的存储引擎到底是如何工作的呢?

\n
    \n
  1. 是的,比尔是对的。
  2. \n
  3. 这一切都归结为链接行和内存块的问题。
  4. \n
\n

引用Oracle 认证专家Martin Zahn 在《Oracle 行链接和迁移的秘密》的文章中的一段话……

\n
\n

链式行对我们的影响不同。这里,就看我们需要的数据了。如果我们有一行包含两列的行,分布在两个块上,则查询:

\n

SELECT column1 FROM table

\n

其中,column1 位于块 1 中,不会导致任何 \xc2\xabtable 获取连续的 row\xc2\xbb。它实际上不必获取column2,它不会一直跟随链接的行。另一方面,如果我们要求:

\n

SELECT column2 FROM table

\n

由于行链接,column2 位于块 2 中,那么您实际上会看到 \xc2\xabtable 获取连续的 row\xc2\xbb

\n
\n

文章的其余部分读起来相当不错!但我在这里只引用与我们手头的问题直接相关的部分。

\n

18 年多过去了,我必须说:谢谢,比尔!

\n

将 MySQL 行映射到数据块

\n