在PostgreSQL中索引空值

Cer*_*rin 23 sql database postgresql indexing

我有一个表格的查询:

select m.id from mytable m
left outer join othertable o on o.m_id = m.id
    and o.col1 is not null and o.col2 is not null and o.col3 is not null
where o.id is null
Run Code Online (Sandbox Code Playgroud)

该查询返回几百条记录,尽管这些表有数百万行,并且需要永久运行(大约一小时).

使用以下方法检查索引统计信息时:

select * from pg_stat_all_indexes
where schemaname <> 'pg_catalog' and (indexrelname like 'othertable_%' or indexrelname like 'mytable_%')
Run Code Online (Sandbox Code Playgroud)

我看到只使用了othertable.m_id的索引,并且根本没有使用col1..3的索引.为什么是这样?

我在一些 地方读过PG传统上无法索引NULL值.但是,据我所知,自从PG 8.3以来这已经发生了变化?我目前正在Ubuntu 10.04上使用PostgreSQL 8.4.我是否需要专门制作一个"部分"或"功能"索引来加速IS NOT NULL查询,或者它是否已经将NULL编入索引并且我只是误解了这个问题?

Mat*_*ood 31

您可以尝试部分索引:

CREATE INDEX idx_partial ON othertable (m_id)
WHERE (col1 is not null and col2 is not null and col3 is not null);
Run Code Online (Sandbox Code Playgroud)

来自文档:http://www.postgresql.org/docs/current/interactive/indexes-partial.html


Sco*_*ley 5

部分索引不会帮助您,因为他们只会找到您不想要的记录.您想要创建包含所需记录的索引.

CREATE INDEX findDaNulls ON othertable ((COALESCE(col1,col2,col3,'Empty')))
WHERE col1 IS NULL AND col2 IS NULL AND col3 IS NULL;

SELECT * 
FROM mytable m
JOIN othertable o ON m.id = o.m_id
WHERE COALESCE(col1,col2,col3,'Empty') = 'Empty';
Run Code Online (Sandbox Code Playgroud)

BTW搜索空左连接通常不如在Postgres中使用EXISTS或NOT EXISTS那么快.