我应该存储空的tsvector值还是NULL值?

min*_*.dk 8 postgresql tsvector

tsvector在列中存储值时,对于没有搜索项的记录,我应该存储空值tsvector还是NULL值?

有关系吗?

存储空载体的性能或存储开销是否有任何差异?

换句话说,当基于例如可空title列的值更新向量时,我是否需要始终将其计算为to_tsvector(coalesce(title,''))(因为在给定参数时to_tsvector返回)或者它是否足够?NULLNULLto_tsvector(title)

Luk*_*der 3

你的问题的逻辑方面

首先,SQL 的语义NULL是 的语义UNKNOWN,而某些数据类型也有“空”值。这些数据类型包括:

  • TEXT''与 不一样NULL::TEXT
  • JSONand JSONB[]or 与or{}不同)NULL::JSONNULL:JSONB
  • X[]ARRAY[]::X[]与 不一样NULL::X[]

还有更多,包括TSVECTOR. 某些东西的空集合的语义总是与NULL值的语义略有不同,值是一个UNKNOWN集合(尽管通常只是用作不存在的集合)。当涉及到使用运算符时,这种区别特别明显,例如

  • '' || 'abc' = 'abc'NULL || 'abc' IS NULL
  • to_tsvector('cats ate rats') @@ to_tsquery('cat & rat') = trueNULL @@ to_tsquery('cat & rat') IS NULL

TSVECTOR从这个意义上说,该决定首先应该是逻辑决定,而不是存储决定,基于以下问题:即使记录没有任何搜索词(proempty TSVECTOR) ,您是否仍然会使用记录的值?或者该功能根本不适用于该特定记录(专业NULL价值)?对于@@操作员来说,它可能不是那么相关,但对于||操作员和其他人来说绝对是这样。

答案并不明显,一般来说也没有明确的正确/错误方法。

您的问题的性能方面

如果这是您的应用程序中对性能高度敏感的情况(例如您有很多空TSVECTOR值),那么也许这个基准可以帮助您做出决定?

我在 Docker 中的 PostgreSQL 14.1 上运行了以下基准测试以获得此结果:

RUN 1, Statement 1: 2.91145
RUN 1, Statement 2: 1.00000 -- The fastest run is 1. The others are multiples of 1
RUN 2, Statement 1: 2.80509
RUN 2, Statement 2: 1.05232
RUN 3, Statement 1: 2.78001
RUN 3, Statement 2: 1.00202
RUN 4, Statement 1: 2.74319
RUN 4, Statement 2: 1.00524
RUN 5, Statement 1: 2.75808
RUN 5, Statement 2: 1.00045
Run Code Online (Sandbox Code Playgroud)
  • 语句 1SELECT v @@ to_tsquery('cat & rat')v tsvector = to_tsvector('');
  • 陈述2是SELECT NULL @@ to_tsquery('cat & rat')

所涉及的事实NULL可能会导致运算符算法中的捷径,与在基准测试中@@查询空值相比,它的性能提高了 2.7 倍。因此,在性能方面TSVECTOR使用似乎确实有好处。NULL

显然,这只是一个基准,不一定反映现实世界的用例,但它应该给您一些潜在差异的提示。

基准代码

对于复制或改编,这里有一个基于此技术的基准

RUN 1, Statement 1: 2.91145
RUN 1, Statement 2: 1.00000 -- The fastest run is 1. The others are multiples of 1
RUN 2, Statement 1: 2.80509
RUN 2, Statement 2: 1.05232
RUN 3, Statement 1: 2.78001
RUN 3, Statement 2: 1.00202
RUN 4, Statement 1: 2.74319
RUN 4, Statement 2: 1.00524
RUN 5, Statement 1: 2.75808
RUN 5, Statement 2: 1.00045
Run Code Online (Sandbox Code Playgroud)