為什麼不走索引, PostgreSQL

2021-09-22 20:43:44 字數 2552 閱讀 4711

原文出處:

">>

有乙個老的問題經常會問道資料庫轉件就是為什麼或者為什麼表的索引沒有被使用?

下面的文章將會簡單的回答這個常見的問題,並按著統計學意義排序。

一、對於外行人來說,你怎麼知道索引沒有被使用呢?

可以使用 explain ; explain analyze 或者 pgadmin 的圖形執行計畫來檢視。 ">>

如果查詢語句確實沒有走索引,那麼我們應該怎麼做呢?

原因: 過時的統計資訊。如果你的資料庫 auto-vacuum 選項是開啟的, 那麼就不會引起這個問題的發生。但是如果你最近剛批量的匯入資料,且新建了索引,那麼很有可能,統計資訊過期,導致查詢優化器不能獲得最新的統計資訊,做出正確的判斷。

方案: vacuum analyze verbose sometable_name;

這裡增加了 verbose 引數,是因為它可以使你看的更清晰 vacuum 是如何運作的。

原因: 查詢優化器認為選擇 table scan 要比選擇 index scan 更快: 做出這種選擇的原因是,查詢涉及的表太小了, 或者我們構建索引的字段重複值太多。

方案: 對於 布林字段構建索引可以認為不是很重要,因為一半是資料,另一半也是資料。不過對這種字段構建部分索引是最好的選擇,值索引活動的資料。

構建的索引與實際過濾欄位的方式不相容。這裡有很多種解決方法

3.1 like %me 將永遠不會選擇索引掃瞄, 但是 like me% 就有可能選擇索引掃瞄

3.2 大小寫的陷阱,例子如下

create index idx_faults_name on faults using btree (fault_name);     --- 構建的索引

--- 查詢語句如下

select * from faults where upper(fault_name) like 'car%' possible fix;

--- 解決辦法如下

create index idx_faults_name on faults using btree (upper(fault_name));

3.3 這個問題很難被意識到, 通過閱讀別人的問題,你就會更好的發現問題。這個問題涉及到了 運算子類

知道這個問題的解決方法的人很少

the other point is that in non-c locales, a standard varchar index isn't

usable for like (the sort order is usually wrong). you can re-initdb

in c locale or create a varchar_pattern_ops index.

booktown=# create index first_name_idx_vpo on auth using btree

(first_name varchar_pattern_ops);

解決方案如下:create index idx_faults_uname_varcahr_parttern on ****ts using btree (upper (fault_name) varchar_parttern_ops);

看到這個解決方案,可能還需要下面的變體和 *in* 子句才能解決問題。

我們並不能證明這是資料庫編碼的問題, 資料的不同或者資料庫版本的不同。 8。2 , 8.3 。 對於pg8.3 我們推薦使用 *utf-8* 的編碼方式初始化資料庫。而對於 8.2 版本是使用的 *sql-ascii*, 這個引數 *varcahr_pattern_ops* 對於 *like* 語句是足夠解決的。

create index idx_faults_uname on faults using btree (upper (****t_name));

select fault_name from faults where upper(fault_name) in ( 'cascadia abduction', 'cabin fever');

3.4 不相容的資料型別。

例如, 我們為日期型別構建索引,但是卻通過將日期型別轉換為 text 型別, 用在比較語句中, 是不選索引掃瞄的。

並不是所有的索引都會被使用。 儘管 pg8.1以上的版本開始支援 bitmap index scan. 該索引掃瞄允許乙個表上構建多個索引, 在查詢執行時,將這些索引構建為 記憶體點陣圖的形式。 如果你構建了很多索引, 不要期望全部候選索引都會被用到。有些時候,執行 table scan 會更高效。

問題: 查詢優化器的不完美。

方案: 期待更美好的查詢優化器的產生。 事實上, postgresql 優化器的能力很不錯的。*if only i could provide hints, i could make this faster *.最好的解決方案就是讓查詢優化器變的更好。隨著資料庫的變化, 優化器也隨之變化, 這就是資料庫程式設計不同於其他程式設計的原因。

不走索引的原因

補充 不走索引的原因,甚至加上hint 還不走索引,那可能是因為你要走索引的這列是nullable,雖然這列沒有空值。將字段改為not null 備註 不走索引的其它原因1 建立組合索引,但查詢謂詞並未使用組合索引的第一列,此處有乙個index skip scan概念。2 在包含有null值的tab...

mysql不走索引總結

在mysql查詢語句中,總會發現明明已經建立了查詢字段索引,可是卻沒有用到,這是因為在mysql中有些查詢語句是用不到索引的,總結如下,以供大家分享。1.like語句 2.列型別為字串型別,查詢時沒有用單引號引起來 3.在where查詢語句中使用表示式 4.在where查詢語句中對字段進行null值...

MySQL not exists 真的不走索引麼

在一些業務場景中,會使用not exists語句確保返回資料不存在於特定集合,部分同事會發現not exists有些場景效能較差,甚至有些網上謠言說 not exists不走索引 哪對於not exists語句,我們如何優化呢?以今天優化的sql為例,優化前sql為 select count 1 f...