Postgre数据库忽略创建的索引?

时间:2010-05-18 23:07:59

标签: sql database database-design optimization postgresql

我有一个Postgre数据库和一个名为my_table的表。该表格中有4列(idcolumn1column2column3)。 id列是主键,列上没有其他约束或索引。 该表有大约200000行。

我想将列column2的值等于(不区分大小写)的所有行打印到'value12'。我用这个:

SELECT * FROM my_table WHERE column2 = lower('value12')

这是此声明的执行计划(set enable_seqscan=on; EXPLAIN SELECT * FROM my_table WHERE column2 = lower('value12')的结果):

Seq Scan on my_table (cost=0.00..4676.00 rows=10000 width=55)
Filter: ((column2)::text = 'value12'::text)

我认为这会变慢,所以我在列column2上创建了一个索引,以便更好地预先搜索:

CREATE INDEX my_index ON my_table (lower(column2))

现在我运行了相同的选择:

SELECT * FROM my_table WHERE column2 = lower('value12')

我希望它更快,因为它可以使用索引。然而它并不快,它和以前一样慢。所以我检查了执行计划,它和以前一样(见上文)。所以它仍然使用顺序情景,它忽略了索引!问题在哪里?

4 个答案:

答案 0 :(得分:4)

此:

SELECT * 
 FROM my_table 
WHERE column2 = lower('value12')

...假设column2中的所有数据都是小写的。如果不是这样的情况将不匹配。

SELECT * 
 FROM my_table 
WHERE LOWER(column2) = LOWER('value12')

在列上使用函数可能会使索引无效。

决策由优化器决定,优化器除了考虑索引之外还要尽可能快地返回结果。据我所知,Postgres没有像MySQL,Oracle或SQL Server中那样提供强制索引使用的语法。

您可以使用SET STATISTICS:

ALTER TABLE <table> ALTER COLUMN <column> SET STATISTICS <number>;
  

此值可以是介于0和1000之间的数字,并帮助PostgreSQL确定应对该列执行的统计信息收集级别。这有助于您控制生成的查询计划,而不会产生缓慢的真空并分析操作,因为会为所有表和列生成大量统计信息。

参考:Performance Tuning PostgreSQL

答案 1 :(得分:2)

您实际上并未比较column2的小写值。您正在将column2的(文字)值与较低版本的'value12'进行比较。

您的意思是与lower(column2)进行比较吗?

SELECT * FROM my_table WHERE lower(column2) = lower('value12')

答案 2 :(得分:1)

您可能需要使用:

WHERE lower(column2) = lower('value12')

通常,涉及列的表达式必须与索引表达式匹配,以便它能够对该索引进行优化。

答案 3 :(得分:0)

除了关于lower()的答案之外,这应该说服PostgreSQL使用索引 - 运行explain来验证。

set enable_seqscan = false;

您可能还想在创建索引后运行vacuum analyze