簡體   English   中英

SQL中WHERE子句的索引性能

[英]Index performance with WHERE clause in SQL

我正在閱讀數據庫書中的索引,我想知道我的假設是否正確,即其中帶有非常量表達式的WHERE子句將不使用索引。 所以如果我有

SELECT * FROM statuses WHERE app_user_id % 10 = 0;

這不會使用在app_user_id上創建的索引。

SELECT * FROM statuses WHERE app_user_id = 5;

將使用app_user_id上的索引。

通常(還有其他選擇)數據庫索引是B樹,這意味着您可以對其進行范圍掃描(包括相等性掃描)。

無法通過單次范圍掃描來評估條件app_user_id % 10 = 0 ,這就是為什么數據庫可能不會使用索引的原因。

它仍然可以決定以另一種方式使用索引,即進行完全掃描:讀取整個表比讀取整個索引需要更多的時間。 另一方面,在讀取索引之后,您仍然可以返回表,因此最終總成本可能更高。

這由數據庫查詢優化器決定。

一些例子:

 select app_user_id from t where app_user_id % 10 = 0

在這里,您根本不需要表,所有必需的數據都在索引中。 數據庫很可能會進行全索引掃描。

 select count(*) from t where app_user_id % 10 = 0

相同。 全索引掃描。

 select count(*) from t

僅當app_user_id為NOT NULL時,才能使用索引來完成此操作(因為NULL數據不在索引中,至少在Oracle上,至少在單列索引上,數據庫可能會對此進行不同的處理)。

一些數據庫不需要為此做訪問表或索引,它們維護元數據中的行數。

 select * from t where app_user_id = 5

這是索引的經典方案。 數據庫可以查看索引樹的一小部分,檢索少量(如果是唯一索引或主索引,則只有一個)行標識符,然后有選擇地從表中獲取它們。

 select * from t where app_user_id between 5 and 10

另一個經典的索引案例。 樹中的范圍掃描返回少量要從表中獲取的rowid。

 select * from t where app_user_id between 5 and 10 order by app_user_id

由於索引掃描返回有序數據,因此您甚至可以免費獲得排序。

 select * from t where app_user_id between 5 and 1000000000

也許在這里您不應該使用索引。 似乎匹配了太多記錄。 在這種情況下,使綁定變量對數據庫隱藏范圍實際上可能是有害的。

 select * from t where app_user_id between 5 and 1000000000 
    order by app_user_id

但是在這里,由於排序將非常昂貴(甚至占用臨時交換磁盤空間),因此按索引順序進行迭代可能很好。 也許。

 select * from t where app_user_id % 10 = 0

這很難決定。 我們需要所有列,因此最終查詢需要觸摸表。 問題是是否首先要通過索引。 該查詢返回整個表的大約10%。 對於索引訪問路徑而言,這可能太過高效了。 如果優化器有理由相信查詢返回的數據少於表的10%,則在執行索引掃描后再訪問該表可能會很好。 如果表非常零散(刪除的行很多占用空間),則相同。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM