你的資料庫索引是否真的起作用了?
阿新 • • 發佈:2018-12-30
為了加快你的查詢,增加正確的索引是必不可少的。 但是過了一段時間,當你的系統增長了,你可能會發現自己大量的索引導致資料庫的寫操作變慢 -- 由於每一次對錶的寫操作,都需要在事務中更新索引。
也許,五年後, 你的資料庫(和你的查詢)在某種方式中進化,不再需要一些索引了。例如,有一些明顯的情況下,這兩個索引是多餘的:
- -- 原設計
- CREATE INDEX ON customer (first_name);
- -- 5年後
- CREATE INDEX ON customer (first_name, last_name);
但在許多其他情況下,事情並沒有那麼明顯。例如…
- 你可能添加了一個在外來鍵上的索引,但隨著表的增長,你的資料庫開始執行更多的雜湊聯接,而不是巢狀迴圈聯接,這種情況下索引並沒有被使用。
- 或者,你已經完全停止查詢姓/名。
- 或者你已經開始使用一個比實際名稱更具選擇性的謂詞。
- 或者你的客戶突然都叫史密斯。
每個人都叫史密斯-倒黴的索引!
如果你的索引不再被使用,你可以(並且應該)刪除它們。
但如何找到未使用的索引
如果你使用的是Oracle資料庫,並且你訪問的是生產系統,實際上有一個非常好的方法來查詢診斷表,以便知道在遊標快取中是否有任何查詢,當前正在使用你的索引。只要執行:
- SELECT sql_fulltext
- FROM v$sql
- WHERE sql_id IN (
- SELECT sql_id
- FROM v$sql_plan
- WHERE (object_owner, object_name)
- = (('OWNER', 'IDX_CUSTOMER_FIRST_NAME'))
- )
- ORDER BY sql_text;
這個查詢做了什麼?它運行遊標快取中的所有SQL語句(V$SQL)並檢查他們每一個是否在遊標快取(v$sql_plan)訪問索引中存在任何執行計劃元素。完成。
當然,如果上述查詢沒有返回任何結果,這並不意味著沒有人使用你的索引。可能還有一個非常罕見的查詢,一年只會發生一次,它被遊標快取清除了。
但是如果你將上述查詢作為一個工作執行一段時間,你就可以得出這樣的結論:如果這個查詢不返回任何行,你的索引可能將不再需要了。
我能發現不需要的索引嗎?
當然!執行一個類似的查詢,列出沒有引用V $ sql_plan表的所有引用:
- SELECT owner, index_name
- FROM all_indexes
- WHERE owner = 'OWNER'
- AND (owner, index_name) NOT IN (
- SELECT object_owner, object_name
- FROM v$sql_plan
- WHERE object_owner IS NOT NULL
- AND object_name IS NOT NULL
- )
- ORDER BY 1, 2
同樣,這並不是說你的索引將永遠不會被使用,只是它們最近還沒有被使用過。現在,我不會真的給你展示使用上述語句的查詢,在PL/SQL迴圈中執行其結果和使用EXECUTE IMMEDIATE刪除所有的索引,因為你可能在你的生產環境中嘗試。但是,以防萬一你想嘗試,這裡有一個提示BEGIN
- BEGIN
- FOR i IN (/* above query here */) LOOP
- EXECUTE IMMEDIATE
- 'DR0P INDEX "' || i.owner || '"."' || i.index_name || '"';
- END LOOP;
- END;
- /
但正如我說的。不要真的這樣做!