代码之家  ›  专栏  ›  技术社区  ›  ryeguy

在PostgreSQL中对列设置“not null”会提高性能吗?

  •  8
  • ryeguy  · 技术社区  · 15 年前

    我知道这是MySQL中的一个好主意。如果我记得正确的话,在MySQL中,它允许索引更有效地工作。

    3 回复  |  直到 7 年前
        1
  •  12
  •   Blake H    9 年前

    如果可以避免列为空,那么最好不要使其为空,因为使用的语义非常混乱;请参见 What is the deal with NULLs? 好好讨论一下这些会给你带来什么麻烦。

    在8.2之前的PostgreSQL版本中,软件不知道如何在最常见的类型索引(B树)上进行比较,这种方式包括在其中查找空值。在相关的位 documentation on index types ,您可以看到描述为“但请注意,空值不等于=且不可索引”。这样做的有效缺点是,如果您指定了一个需要包含空值的查询,那么规划者可能无法使用针对这种情况的明显索引来满足它。作为一个简单的例子,如果您有一个ORDER BY语句可以用索引加速,但是您的查询也需要返回空值,那么优化器就不能使用该索引,因为结果将丢失任何空数据——因此是不完整和无用的。优化器知道这一点,相反,它将对表进行非索引扫描,这可能非常昂贵。

    波斯特雷斯尔 improved this in 8.3 “索引列上的is空条件可与B树索引一起使用”。因此,可以通过尝试索引具有空值的内容而被烧掉的情况已经减少了。但是,由于空语义仍然很痛苦,并且您可能会遇到这样的情况,即8.3计划器也不会因为它们而做您所期望的,因此您仍然应该尽可能使用非空,以降低遇到一个优化得很差的查询的机会。

        2
  •  16
  •   Erwin Brandstetter    7 年前

    设置 NOT NULL 对性能本身没有影响。检查的几个周期-不相关。

    但是您可以通过实际使用空值而不是虚拟值来提高性能。根据数据类型,您可以 节省大量磁盘空间和RAM 从而加速……一切。

    只有在 . 这是一点 每一个 行中的列(是否为空)。对于最多8列的表,使用元组头和行数据之间的空闲字节,空位图实际上是完全空闲的。之后,空间被分配成 MAXALIGN (通常为8字节,覆盖64列)。这一差别被填充物所抵消。所以你付全额(低!)价格为 每行的第一个空值 . 其他空值只能节省空间。

    任何非空值的最小存储要求为1字节( boolean , "char" 、…)或通常 许多的 更多,加上(可能)用于对齐的填充。读起来 data types 或者检查系统表中的详细信息 pg_type .

    有关空存储的详细信息:

        3
  •  2
  •   Magnus Hagander    15 年前

    不,只要您不在表中实际存储空值,索引看起来就会完全相同(而且效率也一样高)。

    不过,将列设置为不为空还有很多其他优点,因此您应该 总是 当您不打算在其中存储空值时,将其设置为:-)