---
# System prepended metadata

title: 資料庫查詢速度優化
tags: [Optimize, Database]

---

過去工作也有優化查詢速度的經驗，但在現在這家公司因為長達十年的累積用戶量，動輒數億的資料累積在客戶表，導致相關查詢緩慢的問題叢生。 在持續優化的過程中也累積了許多相關經驗，特別記錄起來

數據庫: Oracle 11g

## 背景
客戶標籤表，一個用戶有N標籤，就會有 1 * N 的資料筆數
表資料僅約1800萬筆
關聯用戶表，因需要過濾用戶條件
標籤表查詢緩慢問題困擾業務運營與技術團隊良久


## 困難
使用標籤類別搜尋目標用戶，長達 500s - 600s
經團隊與DBA聯合調優，搜尋時間降至 260s - 280s (方式: 根據執行計畫與經驗，調優索引、調優查詢語句、調優子查詢順序、資料下線、調優Oracle優化器 等等)
調優後的查詢時間仍然未達業務可用性，團隊開始研擬OLAP, NOSQL, ES等其他技術方案


## 我採取的作法
#### 找出具體原因: 
1. 表結構分為大、中、小類標籤。 總標籤類別不多，以標籤搜用戶時索引無法發揮作用，selectivity 約20%。 oracle 查詢優化器自動改走full table scan
2. 標籤刪除為軟刪除，資料無法下線
3. 標籤索引過濾後仍可能有八百萬用戶做表關聯，之後才做用戶條件過濾，最後才排序、取偏移量做分頁

#### 嘗試解決方法:
1. 考慮將標籤獨立出一張表，用戶標籤表資料結構設計改為BitMap, Oracle欄位使用RAW 或者 BLOB類型儲存BitMap。 一個用戶只要一條資料，縮減約 80% 的資料數量
2. 思考並討論是否可能刪除無用資料
3. 冗余需要過濾的用戶條件至標籤表，去除表關聯
4. 以標籤大中小類別，做多鍵分區、多層分區
5. 開啟並行查詢


## 效果

查詢縮短為2.8s

1. BitMap: 與團隊及業務運營討論後確認，標籤表內有多個其他資料欄位不可去除，因行資料複雜無法改用BitMap
2. 刪除無用資料: 將刪除資料移至刪除表，減少約 5% 資料量。 並且防杜了表未來無限增生
3. 冗余欄位: 成功去除用戶表關聯，依照執行計畫分析，降低約 25% 查詢時間
4. 多層分區: 11g 不支援多鍵分區 (12c以後)，也不支援三層以上分區 (12c)，因此在大、中類標籤，做主子List雙層分區。 約降低 30% 查詢速度
5. 並行查詢: 針對透過標籤類別尋找用戶的查詢，添加 hint 開啟並行查詢。 並行查詢本就會加快速度，但並行查詢加上多層分區會更大幅度的加快並行效果。 又降低約 30% 的查詢時間 

