是否值得在 Oracle 中按單個值對錶進行分區?
通常,如果您有一個經常查詢表的列,則應該在其上粘貼索引。但是,如果事先知道所有可能的值,是否還值得按此列對錶進行分區?假設您有一個表
AUDIT
,其中的TenantId
列只能包含值:1, 2。 所有SELECT
語句都會有一個WHERE
帶有TenantId
參數的子句。那麼,按 TenantId 對錶進行分區是否有益?如果是這樣,您還會在
TenantId
列上創建索引嗎?partition by list (TENANTID) ( partition TENANT1 values (1), partition TENANT2 values (2) )
我做了一個小實驗:插入隨機生成的TenantId的1M條記錄,從而創建:
- 499652 條 TenantId=1 的記錄
- 500348 條 TenantId=2 的記錄
以下是語句的查詢計劃:
SELECT * FROM table1 WHERE TENANTID=2
普通表(無索引,無分區) 點陣圖索引: 分區:
順便說一句,如果我同時擁有索引和分區,查詢計劃使用分區而不是索引,因此該計劃看起來與上面顯示的第二個完全相同。
顯然分區獲勝,但它是嗎? 顯然,執行計劃中的成本列並不是判斷 SQL 語句響應時間的實際成本的可靠方法。
那麼,最好的方法是什麼?如何選擇一個而不是另一個?
我的觀點是,以呈現的方式對該表進行分區可能是有用的。
如果進行全面掃描,您的查詢將快兩倍(在分區幾乎相等的情況下)。
如果您的查詢具有另一種過濾器/條件並使用索引,則分區沒有用,因為索引的級別幾乎不受值數量加倍的影響。
更新:對於您所做的測試(
SELECT * FROM table1 WHERE TENANTID=2
),可以肯定分區是最好的。點陣圖解決方案需要掃描索引,然後掃描所有包含行的表塊tenantid=2
(它知道行是什麼)。但是分區將導致僅掃描 table 的帶有 tenantid=2 的分區。它們在物理上是分開的tenantid=1
。因此,兩次掃描(索引掃描 + 表掃描)與一次表掃描(可能更小)。
當一列包含很少的不同值時,也就是低基數,就像你的情況一樣,你應該在它上面創建一個點陣圖索引。當您經常按該列查詢時,就是這樣。
以下是有關 Oracle 點陣圖索引的更多資訊: http ://www.dba-oracle.com/oracle_tips_bitmapped_indexes.htm