数据库中列类型的顺序是否会影响查询时间?
例如,具有混合排序(INT,TEXT,VARCHAR,INT,TEXT)的表比具有连续类型(INT,INT,VARCHAR,TEXT,TEXT)的表更难查询吗?
答案 0 :(得分:8)
答案是肯定的,它确实很重要,而且它可能很重要,但通常并不多。
所有I / O都在页面级别完成(通常为2K或4K,具体取决于您的操作系统)。行的列数据彼此相邻存储,除非页面已满,在这种情况下,数据将写入另一页(通常是下一页)。
(根据表定义)所选列之间的列所需的磁盘上数据空间越大,所选列的数据(有时)在不同页面上的可能性就越大。在不同的页面上可能会导致额外的I / O操作(如果在另一页上没有选择其他行)。在最坏的情况下,您选择的每个列可能位于不同的页面上。
以下是一个例子:
create table bad_layout (
num1 int,
large1 varchar(4000),
num2 int,
large2 varchar(4000),
num3 int,
large3 varchar(4000)
);
create table better_layout (
num1 int,
num2 int,
num3 int,
large1 varchar(4000),
large2 varchar(4000),
large3 varchar(4000)
);
比较: 从bad_layout中选择num1,num2,num3; 从better_layout中选择num1,num2,num3;
因为bad_layout每个num列基本上都在不同的页面上,所以每行需要3次i / O操作。相反,对于better_layout,num列通常位于同一页面上。
执行bad_layout查询可能需要大约3倍的时间。
良好的表格布局可以对查询性能产生很大影响。您应该尝试将通常选中的列保持在表格布局中尽可能彼此靠近。
答案 1 :(得分:5)
订单不太重要。运行时间由磁盘访问时间等因素决定,磁盘访问的数量和顺序不会因重新排序行中的数据而发生变化。
唯一的例外是你的行中有一个非常大的项目(比磁盘块大得多,通常是4K?)。如果表中有一个非常大的列,您可能希望将其作为最后一列,这样如果您不访问它,则可能不需要完全分页。但即便如此,您还是必须很难生成一个数据集和访问模式,其差异将是显而易见的。
答案 2 :(得分:3)
在PostgreSQL中,如果首先放置固定宽度列,则会获得优势,因为该访问路径是专门优化的。因此(INT,INT,VARCHAR,TEXT,TEXT)将是最快的(VARCHAR和TEXT的相对顺序无关紧要)。
此外,如果正确管理类型的对齐要求,则可以节省空间,从而可以转化为更高的吞吐量和性能。例如,(INT,BOOL,INT,BOOL)将需要13个字节的空间,因为第三列必须以4字节边界对齐,因此第二列和第三列之间将浪费3个字节的空间。这里更好的是(INT,INT,BOOL,BOOL)。 (无论此行之后的任何内容都可能需要至少4个字节的对齐,因此最后会浪费2个字节。)
答案 3 :(得分:0)
无论你如何订购列,我都建议绝对没有[重大]差异。
SQL Server: http://social.msdn.microsoft.com/Forums/en/sqldatabaseengine/thread/36713a82-315d-45ef-b74e-5f342e0f22fa
我怀疑MySQL也一样。
所有数据都以页面形式读取,因此如果您的数据适合单个页面,则无论您如何订购列。如果磁盘块大小为2K,4K,则需要多个才能满足“8K页面请求”。如果磁盘块大小为64K(对于大型DB系统),则您已经在缓冲其他数据。
不仅如此,如果请求记录,它通常会检索记录的所有页面,包括如果数据跨越多个页面则溢出到第2页和第3页。然后根据检索的数据计算出列。 SQL Server对页内数据有一个限制,大约是8060字节。更大的内容存储在主数据页面之外,类似于TOAST for PostgreSQL,如果未使用该列,则不会检索。 仍然与列在订单中的位置无关。
例如,在SQL Server中,多个位字段一起存储在位图模式掩码中 - 这与您是否将列彼此相邻无关。我怀疑MySQL和PostgreSQL会做同样的事情来优化空间。
注意:[重要] - 这种限定的唯一原因是,可能在从数据页面中提取特定列时,将其放在开头有帮助,因为低级程序集调用不需要在内存块中寻找远。