2010-05-18 20 views
2

我有一個Postgre數據庫和一個名爲my_table的表。該表中有4列(id,column1,column2column3)。 id列是主鍵,列上沒有其他約束或索引。 該表有大約200000行。Postgre數據庫忽略創建的索引?

我想打印出列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列的索引更好prerformance搜索:

CREATE INDEX my_index ON my_table (lower(column2)) 

現在我跑了相同的選擇:

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

我希望它更快,因爲它可以使用索引。但是速度並不快,與以前一樣緩慢。所以我檢查執行計劃,它和以前一樣(參見上文)。所以它仍然使用順序的情況,它忽略了索引!哪裏有問題 ?

回答

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統計:

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

這個值可以是一個數字介於0和1000,並幫助PostgreSQL的確定應該對列進行什麼級別的統計數據收集的。這可以幫助您控制生成的查詢計劃,而不會產生較慢的真空並分析操作,因爲會爲所有表和列生成大量統計信息。

參考:Performance Tuning PostgreSQL

1

您可能需要使用:

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

一般來說,涉及列的表達式,以便匹配索引表達式爲它能夠對指數進行優化。

2

您實際上並不比較column2的小寫字母值。您正在比較column2的(文字)值與'value12'的小寫版本。

您是不是要和lower(column2)比較?

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

除了有關lower()答案,這應該說服PostgreSQL的使用索引 - 運行explain驗證。

set enable_seqscan = false; 

您可能還想在創建索引後運行vacuum analyze