← Về danh sách
Cơ sở dữ liệu
#옵티마이저#RBO#CBO#실행계획#통계정보#127회
Cập nhật lần cuối · 2026-09-14

Bộ tối ưu hóa cơ sở dữ liệu (RBO·CBO)

1. Tổng quan

A. Định nghĩa

Bộ tối ưu hóa (Optimizer) là engine cốt lõi của DBMS, khi thực thi truy vấn SQL sẽ chọn kế hoạch thực thi (execution plan) hiệu quả nhất trong số nhiều đường thực thi (access path·join order·join method) cho cùng một kết quả. Khi người dùng biểu diễn 'cái gì (what)' mình muốn bằng SQL khai báo, vai trò của bộ tối ưu hóa là quyết định xử lý 'như thế nào (how)'.

Chìa khóa để hiểu bộ tối ưu hóa là 'một câu SQL có hàng chục đến hàng nghìn cách thực thi, và tùy theo cách được chọn mà thời gian phản hồi chênh lệch hàng trăm đến hàng chục nghìn lần'. Ví dụ, ngay cả truy vấn đơn giản nối hai bảng A·B, thời gian thực thi cũng chênh lệch cực đoan tùy theo tổ hợp đọc bảng nào trước (driving table), dùng chỉ mục hay quét toàn bộ (access path), dùng phương thức nối nào (Nested Loop·Hash·Sort Merge). Trong CSDL quan hệ, SQL là 'ngôn ngữ khai báo' nên người dùng không chỉ định thủ tục xử lý, và trí tuệ tự động quyết định chính thủ tục đó chính là bộ tối ưu hóa.

Nếu không có bộ tối ưu hóa, lập trình viên phải tự tay viết thứ tự thực thi vật lý tối ưu cho mỗi truy vấn và phải tinh chỉnh lại mỗi khi lượng·phân bố dữ liệu thay đổi. Bộ tối ưu hóa hấp thụ gánh nặng này vào bên trong DBMS, để người dùng chỉ tập trung vào truy vấn logic và giao tối ưu hóa vật lý cho engine. Tuy nhiên, tùy theo 'lấy gì làm tiêu chí phán đoán tối ưu' mà bộ tối ưu hóa chia thành hai nhánh: RBO (Rule Based Optimizer) tuân theo thứ tự ưu tiên của các quy tắc cố định, và CBO (Cost Based Optimizer) tính chi phí dựa trên thống kê dữ liệu thực tế. Ngày nay, hầu như mọi DBMS thương mại·mã nguồn mở đều chọn CBO làm tiêu chuẩn.

B. Sự cần thiết và vị trí

Dữ liệu càng lớn và truy vấn càng phức tạp thì 'việc lựa chọn cách thực thi' càng quyết định hiệu năng. Bộ tối ưu hóa đảm nhận giai đoạn tối ưu hóa trong pipeline xử lý SQL (phân tích cú pháp → tối ưu hóa → thực thi); khi parser kiểm tra cú pháp·ngữ nghĩa và tạo ra các dạng truy vấn tương đương về logic, bộ tối ưu hóa chọn kế hoạch rẻ nhất về mặt vật lý trong số đó và chuyển cho bộ thực thi (row source generator). Tức là bộ tối ưu hóa tương ứng với 'bộ não của DBMS', tìm đường tối ưu để bảo đảm hiệu năng mà người dùng không cần bận tâm.

Tầm quan trọng của bộ tối ưu hóa tăng phi tuyến khi quy mô hệ thống lớn lên. Với dữ liệu nhỏ, lập kế hoạch nào thì khác biệt cảm nhận cũng nhỏ, nhưng trong môi trường dữ liệu lớn·đồng thời cao, chỉ một kế hoạch sai cũng có thể độc chiếm CPU·bộ nhớ·I/O và làm sụp đổ khả năng phản hồi của toàn hệ thống. Do đó, hiểu bộ tối ưu hóa không chỉ là kiến thức tối ưu hiệu năng đơn thuần, mà là vấn đề nền tảng của vận hành dịch vụ ổn định và hiệu quả tài nguyên, là năng lực cốt lõi gắn trực tiếp với tinh chỉnh DB·ước tính dung lượng·quản lý SLA.

2. Vị trí của bộ tối ưu hóa trong luồng xử lý SQL

Để hiểu bộ tối ưu hóa can thiệp khi nào·dựa trên căn cứ gì, cần xem toàn bộ luồng xử lý một câu SQL. Sơ đồ quy trình chi tiết dưới đây cho thấy các giai đoạn từ phân tích cú pháp đến thực thi·phản hồi thống kê.

flowchart TB
  SQL["Truy vấn SQL"] --> PAR["Parser (Parser)<br/>Kiểm tra cú pháp·ngữ nghĩa"]
  PAR --> TRANS["Biến đổi truy vấn<br/>(Query Transformation)"]
  TRANS --> OPT["Bộ tối ưu hóa<br/>(Sinh ứng viên kế hoạch·đánh giá chi phí)"]
  STAT["Thông tin thống kê<br/>(bảng·chỉ mục·histogram)"] --> OPT
  OPT --> PLAN["Chọn kế hoạch thực thi tối ưu"]
  PLAN --> EXEC["Bộ thực thi (Row Source Generator)"]
  EXEC --> RES["Trả kết quả"]
  EXEC -. Phản hồi cardinality .-> STAT
  style OPT fill:#e8f0fe,stroke:#2f6fed,stroke-width:2px
  style STAT fill:#fef3e8,stroke:#ed8f2f,stroke-width:2px

Các lựa chọn vật lý mà bộ tối ưu hóa xem xét khi tạo kế hoạch ứng viên gồm ba trục chính. Thứ nhất là đường truy cập (access path), phán đoán giữa quét toàn bảng (Full Table Scan) và quét chỉ mục cái nào rẻ hơn. Nếu chỉ lọc ra ít dòng thì chỉ mục có lợi, nếu lọc ra nhiều dòng thì quét toàn bộ có lợi. Thứ hai là thứ tự nối (join order), chi phí sau đó thay đổi tùy theo chọn bảng nào để đọc trước và thu nhỏ tập kết quả (driving table). Thứ ba là phương thức nối (join method), chọn phù hợp với quy mô dữ liệu giữa Nested Loop có lợi cho tập nhỏ, Hash Join có lợi cho nối bằng lớn, và Sort Merge phù hợp với tập lớn đã sắp xếp. Tổ hợp của ba trục này làm bùng nổ số trường hợp của kế hoạch thực thi, và việc tìm điểm chi phí thấp nhất trong không gian khổng lồ đó chính là công việc của bộ tối ưu hóa.

Diễn giải luồng này thành văn: trước tiên parser kiểm tra cú pháp SQL và sự tồn tại·quyền của đối tượng. Tiếp theo, ở giai đoạn biến đổi truy vấn (query transformation), bộ tối ưu hóa viết lại truy vấn thành dạng tương đương về logic nhưng dễ tối ưu hơn bằng hợp nhất truy vấn con (view merging), đẩy điều kiện (predicate pushing), mở rộng OR, v.v. Sau đó, ở giai đoạn tối ưu hóa chính thức, nó sinh nhiều ứng viên kế hoạch thực thi, ước tính chi phí từng ứng viên và chọn kế hoạch chi phí thấp nhất. Thứ được tham chiếu mang tính quyết định lúc này chính là thông tin thống kê, và nếu số dòng thực tế được xử lý sau khi thực thi khác nhiều so với ước tính, thông tin đó được phản hồi lại vào thống kê (phản hồi cardinality) để cải thiện lần thực thi sau. Tóm lại, chất lượng phán đoán của bộ tối ưu hóa phụ thuộc tuyệt đối vào 'độ chính xác của thống kê'.

3. RBO vs CBO: khác biệt về tiêu chí phán đoán

Hai phương thức tối ưu hóa khác nhau về bản chất ở 'chọn đường thực thi dựa trên căn cứ gì'. Sơ đồ cấu trúc dưới đây cho thấy cùng một câu SQL đi đến kế hoạch dựa trên các căn cứ khác nhau như thế nào trong hai phương thức.

flowchart LR
  S["Truy vấn SQL"] --> O["Bộ tối ưu hóa"]
  O --> R["RBO<br/>Bảng thứ tự ưu tiên quy tắc"]
  O --> C["CBO<br/>Tính chi phí dựa trên thống kê"]
  R --> RP["Chọn đường có<br/>thứ hạng quy tắc cao"]
  C --> CP["Chọn đường có<br/>chi phí nhỏ nhất"]
  RP --> P["Kế hoạch thực thi"]
  CP --> P
  style O fill:#e8f0fe,stroke:#2f6fed,stroke-width:2px

A. RBO (bộ tối ưu hóa dựa trên quy tắc)

RBO lập kế hoạch thực thi theo danh sách quy tắc và thứ tự ưu tiên định sẵn. Chẳng hạn, mỗi đường truy cập có thứ hạng (rank) cố định như 'truy cập chỉ mục một dòng > chỉ mục duy nhất > chỉ mục phạm vi > quét toàn bảng', và bộ tối ưu hóa vô điều kiện chọn đường có thứ hạng cao bất kể lượng·phân bố thực tế của dữ liệu. Ưu điểm là đơn giản và kết quả có thể dự đoán. Nó hoạt động ngay cả khi không có thống kê, và cùng một câu SQL luôn tạo ra cùng một kế hoạch.

Tuy nhiên, giới hạn chí mạng của RBO là 'không nhìn vào dữ liệu thực tế'. Có chỉ mục là dùng chỉ mục vô điều kiện, nên ngay cả với truy vấn phải đọc 900 nghìn trên tổng 1 triệu dòng, nó vẫn dùng chỉ mục, khiến I/O ngẫu nhiên bùng nổ và phát sinh nghịch lý chậm hơn nhiều so với quét toàn bộ. Cách này dùng được khi dữ liệu còn nhỏ, nhưng trong môi trường hiện đại với dữ liệu lớn·phân bố đa dạng thì lựa chọn sai xảy ra thường xuyên nên trên thực tế đã bị loại bỏ. Với Oracle, sau khi đưa CBO vào, RBO chỉ được dùng khi không có thống kê hoặc khi yêu cầu tường minh, rồi ở các phiên bản sau được xếp vào dạng không còn được hỗ trợ (obsolete·deprecated).

Lý do căn bản hơn khiến RBO bị loại bỏ nằm ở mâu thuẫn cấu trúc 'dữ liệu thay đổi nhưng quy tắc cố định'. Dù bảng từ vài nghìn dòng lúc đầu dịch vụ tăng lên hàng trăm triệu dòng sau vài năm vận hành, RBO vẫn tạo cùng kế hoạch với cùng thứ hạng quy tắc. Đường tối ưu phải thay đổi theo sự tăng trưởng·thay đổi phân bố của dữ liệu, nhưng RBO không có phương tiện phản ánh điều đó. Ngược lại, CBO chỉ cần cập nhật thống kê là tự lập kế hoạch khác phù hợp với quy mô dữ liệu ngay cả với cùng câu SQL. Sự có hay không 'năng lực thích ứng với thay đổi' này đã quyết định số phận của hai phương thức, và vì vậy DBMS hiện đại không có ngoại lệ đều lấy CBO làm mặc định.

B. CBO (bộ tối ưu hóa dựa trên chi phí)

CBO thực sự tính chi phí (cost) của từng đường thực thi dựa trên thông tin thống kê như kích thước bảng·phân bố dữ liệu·độ chọn lọc chỉ mục·clustering factor và chọn kế hoạch rẻ nhất. Ở đây chi phí là giá trị ước tính chuẩn hóa đại khái 'lượng dùng CPU + số lần I/O', và bộ tối ưu hóa ước tính số dòng xử lý dự kiến (cardinality) và chi phí cho mỗi kế hoạch ứng viên để so sánh. Vì dựa trên thống kê nên có thể chọn một cách thông minh phù hợp với tình trạng dữ liệu, đó là lý do nó trở thành tiêu chuẩn của mọi DBMS chủ yếu ngày nay.

Hiệu năng của CBO phụ thuộc vào 'độ tươi của thống kê'. Nếu thống kê cũ và lệch với dữ liệu thực tế (stale statistics), bộ tối ưu hóa sẽ lập kế hoạch sai lệch dựa trên cardinality sai. Ví dụ, nếu thống kê của bảng mới tăng đột biến vẫn còn theo mức nhỏ ngày trước, bộ tối ưu hóa phán đoán sai 'bảng này nhỏ' và chọn nối Nested Loop không phù hợp, kết quả là truy vấn lẽ ra xong trong vài giây lại mất hàng chục phút. Vì vậy, cốt lõi của vận hành CBO là thu thập thống kê định kỳ·tự động.

Phân loại RBO (dựa trên quy tắc) CBO (dựa trên chi phí)
Tiêu chí phán đoán Quy tắc·thứ tự ưu tiên cố định Tính chi phí dựa trên thống kê
Phản ánh dữ liệu Không (bỏ qua dữ liệu) Có (kích thước·phân bố·thống kê)
Ưu điểm Đơn giản·dự đoán được Tối ưu hóa thông minh phù hợp tình trạng dữ liệu
Nhược điểm Phát sinh kém hiệu quả do bỏ qua tình trạng thực tế Hiệu năng phụ thuộc độ chính xác của thống kê
Vị thế hiện tại Đã loại bỏ (obsolete) Tiêu chuẩn trên thực tế

4. Tính chi phí của CBO và các yếu tố tinh chỉnh thực tiễn

Quá trình CBO tính chi phí rốt cuộc là 'chuỗi ước tính cardinality'. Với mỗi điều kiện (predicate), ước tính bao nhiêu dòng được lọc ra bằng độ chọn lọc (selectivity), rồi chuyển số dòng kết quả làm đầu vào cho phép toán tiếp theo (nối·sắp xếp) để lại tính chi phí. Nếu mắt xích đầu tiên của chuỗi này — ước tính độ chọn lọc — bị lệch thì mọi ước tính sau đó đều lệch dây chuyền, nên histogram cho biết chính xác phân bố dữ liệu rất quan trọng. Ở cột có phân bố giá trị không đồng đều (ví dụ: một mã cụ thể chiếm 95% tổng số), nếu không có histogram bộ tối ưu hóa sẽ phán đoán sai mỗi giá trị theo phân bố đều. Các phiên bản mới nhất hỗ trợ thêm histogram top-frequency·hybrid bên cạnh frequency·height-balanced để biểu diễn chính xác hơn phân bố lệch.

Các yếu tố tinh chỉnh thực tiễn sẽ được tổng hợp nhất quán nếu hiểu tất cả đều là phương tiện 'giúp bộ tối ưu hóa lập kế hoạch tốt'. Các mục trong bảng dưới đây không độc lập với nhau mà tạo thành một luồng: cập nhật thống kê, đọc kế hoạch thực thi để chẩn đoán vấn đề, rồi chỉ can thiệp bằng hint khi cần.

Yếu tố tinh chỉnh Nội dung và lý do
Quản lý thông tin thống kê CBO phụ thuộc thống kê → bắt buộc duy trì trạng thái mới nhất bằng thu thập thống kê tự động
Phân tích kế hoạch thực thi Chẩn đoán điểm nghẽn (I/O quá mức·nối sai) bằng EXPLAIN PLAN·thống kê thực thi thực tế
Histogram Ngăn phán đoán sai độ chọn lọc ở cột phân bố lệch
Hint (Hint) Khi bộ tối ưu hóa phán đoán sai, lập trình viên dẫn dắt tường minh đường truy cập·phương thức nối
Biến ràng buộc (bind variable) Giảm gánh nặng hard parse nhờ tái sử dụng kế hoạch thực thi (soft parse)

Đánh đổi cần chú ý ở đây là tương tác giữa biến ràng buộc và histogram. Biến ràng buộc tái sử dụng kế hoạch thực thi để giảm chi phí phân tích cú pháp, nhưng nếu dùng biến ràng buộc cho cột phân bố lệch, 'kế hoạch được tối ưu cho giá trị đến đầu tiên' có thể bị tái sử dụng cho các giá trị khác sau đó, gây kém hiệu quả (tác dụng phụ bind peeking). Trong trường hợp này, bổ khuyết bằng tính năng như adaptive cursor sharing để phân nhánh kế hoạch theo phân bố giá trị. Tức là một kỹ thuật tối ưu có thể gây tác dụng ngược trong tình huống khác, nên thói quen thực sự đọc và kiểm chứng kế hoạch thực thi là điểm xuất phát của tinh chỉnh.

A. Sự cố hiệu năng do ước tính cardinality sai (ví dụ)

Kịch bản điển hình khi phán đoán sai của CBO lan thành sự cố thực tế là trường hợp 'chọn nối Nested Loop cho bảng lớn bị nhầm là bảng nhỏ'. Ví dụ, giả sử batch ban đêm nạp hàng triệu dòng vào bảng đơn hàng nhưng thống kê không được cập nhật nên bộ tối ưu hóa ước tính 'bảng này có vài nghìn dòng'. Bộ tối ưu hóa chọn Nested Loop có lợi cho tập nhỏ (duyệt lặp bảng trong cho mỗi dòng ngoài), nhưng thực tế phát sinh hàng triệu lần duyệt lặp, khiến truy vấn lẽ ra xong trong vài giây chiếm CPU và I/O hàng chục phút. Nếu là truy vấn nghiệp vụ ban ngày thì lập tức dẫn đến chậm trễ dịch vụ.

Chẩn đoán và xử lý sự cố này đi theo đúng nguyên lý của bộ tối ưu hóa. Trước tiên, xác nhận sự chênh lệch giữa cardinality ước tính (E-Rows) và số dòng thực tế (A-Rows) trong kế hoạch thực thi để chỉ ra bộ tối ưu hóa đã phán đoán sai ở đâu. Nếu nguyên nhân gốc là thống kê cũ thì cách chuẩn là thu thập lại thống kê, còn nếu nguyên nhân là lệch giá trị cụ thể thì tạo histogram để sửa ước tính độ chọn lọc. Chỉ trong tình huống khẩn cấp cần đảo ngược kế hoạch ngay mới xử lý tạm bằng hint cưỡng chế phương thức nối, nhưng sau đó phải giải quyết nguyên nhân gốc bằng thống kê·chỉ mục để gỡ bỏ sự phụ thuộc vào hint. Ví dụ này đồng thời cho thấy mệnh đề 'hiệu năng của CBO phụ thuộc độ chính xác của thống kê' và nguyên tắc 'đọc kế hoạch thực thi để đối chiếu ước tính với thực tế là bước đầu tiên của tinh chỉnh'.

5. Chuyên sâu: tối ưu hóa thích ứng (Adaptive Query Optimization)

Điểm yếu căn bản của CBO là 'ước tính lập trước khi thực thi có thể khác thực tế'. Dù thống kê tốt đến đâu, ước tính cardinality vẫn có thể trượt ở các phép nối·điều kiện phức tạp, và kết quả là kế hoạch sai có thể bị cố định. Để bổ khuyết, tối ưu hóa truy vấn thích ứng (Adaptive Query Optimization) ra đời, và được tổng hợp thành một nhóm tính năng trong Oracle Database 12c.

Thứ nhất, kế hoạch thích ứng (Adaptive Plans) là cách 'hoãn quyết định kế hoạch đến thời điểm thực thi' với các phép nối khó ước tính cardinality. Bộ tối ưu hóa cài bộ thu thập thống kê (statistics collector) vào kế hoạch thực thi, và nếu số dòng thực tế được xử lý khác nhiều so với ước tính thì chuyển đổi kế hoạch ngay trong khi thực thi, chẳng hạn đổi phương thức nối từ Nested Loop sang Hash Join. Thứ hai, tái tối ưu hóa tự động (Automatic Reoptimization) và tiền thân của nó là phản hồi cardinality (cardinality feedback, đưa vào từ 11gR2) lưu cardinality thực tế sau một lần thực thi, rồi phản ánh giá trị đó để biên dịch lại thành kế hoạch tốt hơn ở lần thực thi sau. Thứ ba, quản lý kế hoạch SQL (SQL Plan Management) cố định kế hoạch đã được kiểm chứng làm baseline, ngăn 'hồi quy kế hoạch (plan regression)' khi kế hoạch đột ngột xấu đi do thay đổi thống kê.

Hàm ý thực tiễn của xu hướng này rất rõ ràng. Nếu trước đây bộ tối ưu hóa chỉ xử lý 'theo đúng kế hoạch lập một lần trước khi thực thi', thì CBO hiện đại đang tiến hóa theo hướng 'vừa thực thi vừa học và tự hiệu chỉnh'. Hơn nữa, gần đây các tính năng CSDL tự vận hành (autonomous) ước tính cardinality bằng học máy (learned cardinality estimation) hoặc học lịch sử thực thi để tự động đề xuất tinh chỉnh đã được thương mại hóa, và bộ tối ưu hóa đang vẽ nên quỹ đạo quy tắc (RBO) → chi phí dựa trên thống kê (CBO) → thích ứng trong khi thực thi (adaptive) → tự trị dựa trên học.

6. Các điểm cần lưu ý và hàm ý (góc nhìn Kỹ sư chuyên nghiệp)

  1. Cập nhật thông tin thống kê là sinh mệnh của CBO. CBO tính chi phí dựa trên thống kê, nên nếu thống kê cũ (stale) hoặc không chính xác thì hiệu năng giảm mạnh do kế hoạch thực thi sai. Phải vận hành tác vụ thu thập thống kê tự động, và ngay sau khi nạp dữ liệu lớn (batch·migration) phải cập nhật thống kê thủ công để căn cứ phán đoán của bộ tối ưu hóa luôn khớp với dữ liệu thực tế.
  2. Tin bộ tối ưu hóa nhưng nhất định phải kiểm chứng. Với phần lớn truy vấn, CBO tìm được tối ưu, nhưng ở các phép nối nhiều bảng phức tạp·phân bố lệch thì phán đoán sai vẫn xảy ra. Phải lấy quy trình kiểm chứng làm tiêu chuẩn của tinh chỉnh SQL: so sánh kế hoạch thực thi (EXPLAIN PLAN) và thống kê thực thi thực tế để xác nhận chênh lệch giữa cardinality ước tính và số dòng thực tế, rồi hiệu chỉnh các điểm chênh lệch lớn bằng histogram·hint.
  3. Dùng hint thận trọng như phương sách cuối cùng. Cưỡng chế kế hoạch bằng hint cải thiện ngay trước mắt, nhưng khi phân bố dữ liệu thay đổi, kế hoạch cưỡng chế đó có thể trở thành xiềng xích. Phải giải quyết nguyên nhân gốc (thống kê·thiết kế chỉ mục) trước, và chỉ áp dụng hint có giới hạn trong những tình huống ngoại lệ khó hiệu chỉnh nguyên nhân để giữ khả năng bảo trì.
  4. Xây dựng hệ thống ổn định kế hoạch và ngăn hồi quy. 'Hồi quy kế hoạch' — kế hoạch của truy vấn đang chạy tốt đột ngột xấu đi do thay đổi thống kê hoặc nâng cấp phiên bản — dẫn thẳng đến sự cố vận hành. Cần quản trị: tận dụng quản lý kế hoạch SQL (plan baseline)·tính năng tối ưu hóa thích ứng để bảo vệ kế hoạch đã kiểm chứng, và khi thay đổi thì chuyển đổi sau khi qua kiểm thử hồi quy hiệu năng.
  5. Phản ánh sự tiến hóa sang tối ưu hóa thích ứng·tự trị vào thiết kế. CBO hiện đại phát triển theo hướng hiệu chỉnh kế hoạch trong khi thực thi và tự động hóa tinh chỉnh bằng học, nên khi thiết kế hệ thống mới phải bật các tính năng này và bảo đảm chỉ số giám sát (lịch sử thay đổi kế hoạch·tái tối ưu hóa), giảm sự phụ thuộc vào tinh chỉnh thủ công của DBA và quản lý liên tục hiệu năng của môi trường truy vấn quy mô lớn.

Tài liệu tham khảo


Tóm tắt một câu: Bộ tối ưu hóa là bộ não của DBMS chọn kế hoạch thực thi tối ưu trong số nhiều đường thực thi của SQL, chia thành RBO với quy tắc cố định (đã loại bỏ) và CBO tính chi phí dựa trên thống kê (tiêu chuẩn hiện nay); hiệu năng của CBO phụ thuộc vào việc cập nhật thông tin thống kê và ước tính cardinality chính xác, được tinh chỉnh bằng phân tích kế hoạch thực thi·histogram·hint, và đang tiến hóa sang tối ưu hóa thích ứng·tự trị tự hiệu chỉnh trong khi thực thi.