查询速度基于列的顺序

时间:2011-01-03 06:22:21

标签: sql mysql postgresql

数据库中列类型的顺序是否会影响查询时间?

例如,具有混合排序(INT,TEXT,VARCHAR,INT,TEXT)的表比具有连续类型(INT,INT,VARCHAR,TEXT,TEXT)的表更难查询吗?

4 个答案:

答案 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)

无论你如何订购列,我都建议绝对没有[重大]差异。

PostgreSQL:http://social.msdn.microsoft.com/Forums/en-US/sqldatabaseengine/thread/a7ce8a90-22fc-456d-9f56-4956c42a78b0

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会做同样的事情来优化空间。

注意:[重要] - 这种限定的唯一原因是,可能在从数据页面中提取特定列时,将其放在开头有帮助,因为低级程序集调用不需要在内存块中寻找远。