除了Craig的详尽答案之外,我还想补充一点,您所参考的书的封面上写着:
涵盖Oracle,DB2和SQL Server
因此,我不相信它会成为PostgreSQL特别有用的建议。每个RDBMS都可能出奇的不同!
我对您的原始问题有些困惑,但是下面的示例说明了本书的这一部分并非100%正确。为避免进一步的混乱,请参见以下整个段落,您可以在Google图书搜索中查看该段落。
数据库假定Indexed_Col IS NOT NULL覆盖的范围太大而无用,因此数据库不会从这种情况驱动到索引。在极少数情况下,具有任何非空值非常罕见,因此对所有可能的非空值进行索引范围扫描是有益的。在这种情况下,如果您可以找出所有可能值范围的安全下限或上限,则可以使用诸如Positive_ID_Column> -1或Date_Column> TO_DATE('0001/01/01' ,'YYYY / MM / DD')。
实际上,Postgres可以(在以下伪造的情况下)使用索引来满足IS NOT NULL
查询,而无需像建议的那样添加范围扫描合并Positive_ID_Column > -1
。有关在特定情况下Postgres为什么选择此索引的信息,请参阅有关Craig问题的评论,以及有关使用部分索引的说明。
CREATE TABLE bar (a int);
INSERT INTO bar (a) SELECT NULL FROM generate_series(1,1000000);
INSERT INTO bar (a) VALUES (1);
CREATE INDEX bar_idx ON bar (a);
EXPLAIN ANALYZE SELECT * FROM bar WHERE a IS NOT NULL;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------
Index Only Scan using bar_idx on bar (cost=0.42..8.44 rows=1 width=4) (actual time=0.094..0.095 rows=1 loops=1)
Index Cond: (a IS NOT NULL)
Heap Fetches: 1
Total runtime: 0.126 ms
(4 rows)
顺便说一下,这是Postgres 9.3,但我相信结果将与9.1大致相似,尽管它不会使用“仅索引扫描”。
编辑:我看到您已经澄清了您的原始问题,并且您显然想知道为什么Postgres在简单的示例中不使用索引:
CREATE TABLE my_table(
a varchar NOT NULL
);
CREATE INDEX ix_my_table ON my_table(a);
SELECT a from my_table;
可能是因为表中没有任何行。因此,添加一些测试数据和ANALYZE my_table;
。