- vừa được xem lúc

Tìm hiểu B-Tree trong Database

0 0 4

Người đăng: Bao Vo

Theo Viblo Asia

🧠 Mở đầu

Thời gian đầu mới đi làm, công ty có dự án liên quan đến Nông nghiệp, làm cho khách hàng Nhật. Phía Nhật lo phần thiết kế database và tài liệu, còn team ở Việt Nam chịu trách nhiệm coding và testing.

Mọi thứ diễn ra suôn sẻ. Code xong chức năng, test ok, client duyệt, mọi người đều vui.

Cho đến khi... dữ liệu bắt đầu nhiều lên.

Ứng dụng bỗng trở nên chậm chạp. Tôi nghi ngờ ngay JavaScript, vì lúc đó dùng Ajax để gọi backend và hiển thị dữ liệu. Nghĩ rằng dữ liệu lớn làm javascript render chậm. Nhưng khi debug sâu bên trong vấn đề nằm ở cách viết câu SQL và thiết kế index trong database


❓ Những câu hỏi lúc đó...

  • Vì sao LIKE '%abc' không dùng được index?
  • Vì sao khi dùng hàm trong WHERE, index lại không hoạt động?
  • Vì sao đã tạo index index_AB(column_A, column_B) mà tìm theo column_B='abc' vẫn không tận dụng được index?

Câu trả lời cho tất cả các câu hỏi đó nằm trong cấu trúc của B-Tree.

Hãy tưởng tượng B-Tree giống như một thư viện được sắp xếp gọn gàng. Thay vì phải lục tung từng cuốn sách, bạn có thể tra cứu nhanh nhờ cấu trúc được phân tầng – chính xác và hiệu quả.

B-Tree


🌳 Cấu trúc cơ bản của B-Tree

🔹 Index với một column

Khi bạn tạo index trên một column duy nhất, cấu trúc B-Tree sẽ trông như sau:

(Hình ảnh giản luợc) Index đơn column

❓ Vì sao LIKE '%abc' không dùng index?

👉 Vì B-Tree được xây dựng để duyệt từ ký tự đầu tiên. Khi bắt đầu bằng %, bạn đã mất gốc – không xác định được điểm khởi đầu trong cây, khiến việc tìm kiếm phải duyệt toàn bộ dữ liệu. Index lúc này bị vô hiệu.

❓ Vì sao khi dùng hàm (LOWER(column_name), LTRIM(column_name)...) trong điều kiện thì index không chạy?

👉 Vì B-Tree chỉ hoạt động dựa trên giá trị gốc của column. Khi bạn áp dụng hàm, cơ sở dữ liệu phải tính toán lại từng dòng, và các giá trị sau xử lý không còn khớp với cây đã xây dựng. Kết quả: Index không được tận dụng.


🔹 Index với nhiều column

Giả sử bạn tạo index: index_AB(column_A, column_B), thì cấu trúc B-Tree sẽ ưu tiên column đầu tiên để xây dựng.

Ví dụ với index_ho_ten(ho, ten), cây sẽ được sắp xếp theo thứ tự của ho trước, sau đó mới đến ten.

(Hình giản lược, mô phỏng cấu trúc B-Tree) Index nhiều column

❓ Vì sao WHERE column_B = 'abc' không dùng được index?

👉 Vì cây B-Tree khởi động từ column_A. Nếu bạn không lọc theo column_A, thì không thể định hướng để duyệt đến column_B. Cơ bản là không có đường vào cây.

❓ Vậy cột nào nên là column đầu tiên trong index?

👉 Là cột có tính phân biệt cao (distinctive) – tức giá trị ít bị trùng lặp. Điều này giúp cây phân nhánh tốt hơn, giảm đáng kể số dòng cần duyệt khi truy vấn.


⚠️ Ghi chú thêm với Column is_deleted

Nhiều hệ thống có sử dụng xóa luận lý (logical delete), nghĩa là không xóa thật dữ liệu mà chỉ cập nhật is_deleted = 1.

is_deletedtính phân biệt thấp (đa số giá trị là 0), nhưng nếu bạn thường xuyên truy vấn kiểu:

WHERE is_deleted = 0 AND name LIKE 'A%'

thì việc tạo index như index_del_name(is_deleted, name) lại giúp truy vấn nhanh hơn: lọc nhanh is_deleted = 0 trước, sau đó tìm tiếp theo name

💡 Tuy nhiên, đây không phải quy tắc cố định. Nếu truy vấn của bạn không lọc is_deleted, mà chỉ tìm theo name, thì nên đặt is_deleted sau trong thứ tự index.

(Tùy bài toán cụ thể ta sẽ đặt is_deleted ở vị trí phù hợp, sau khi tạo index, ta phải thử lại, xem query plan để phán đoán tính hiệu quả của nó như thế nào)


✅ Tổng kết

Khi đã nắm được cơ bản cách B-Tree xây dựng và duyệt, bạn sẽ biết được:

  • Vì sao một số câu SQL không thể dùng index.
  • Cách lựa chọn column đầu tiên trong index ảnh hưởng ra sao đến hiệu năng.
  • Index rất quan trọng trong bài toán truy xuất dữ liệu từ database, nếu không thiết kế không tốt hệ thống sẽ chậm khi dữ liệu lớn dần

✌️ Cảm ơn bạn đã đọc đến đây. Nếu thấy hữu ích, hãy chia sẻ cho bạn bè đang vật lộn với Index nhé!

Bình luận

Bài viết tương tự

- vừa được xem lúc

Performance Optimization 105: Database bottleneck - Đuổi bắt kẻ tội đồ

Hành trình đuổi bắt giáo sư Moriarty của thế giới bottleneck: database. Cuộc chiến không hồi kết này rút cục sẽ ra sao? Liệu mọi chuyện có kết thúc tại thác Reichenback không hay Moriarty sẽ mãi là bóng ma ám ảnh service của chúng ta mãi.

0 0 64

- vừa được xem lúc

003: Hiểu về Index để tăng performance với PostgreSQL P2

Bài viết nằm trong series Performance optimization với PostgreSQL. . . B-Tree index.

0 0 544

- vừa được xem lúc

004: Hiểu về Index để tăng performance với PostgreSQL P3

Bài viết nằm trong series Performance optimization với PostgreSQL. . 1) What. Trước khi đi vào chi tiết, cùng xem lại nhiệm vụ, tính chất của hash function:.

0 0 127

- vừa được xem lúc

Case Study tối ưu sử dụng Partition và Index để tối ưu câu lệnh từ 30 phút xuống còn 0.01s như thế nào?

Đây là một bài toán tối ưu thực tế , tôi đã áp dụng kỹ thuật tối ưu này cho rất nhiều doanh nghiệp lớn: hệ thống Core chứng khoán, cơ sở dữ liệu core billing của đơn vị viễ

0 0 40

- vừa được xem lúc

[POSTGRES] Tìm Hiểu Nâng Cao Về Index Trong Database

indexing trong postgres là một tiến trình tạo một data-structure hỗ trợ cho việc optimized để search cũng như retrieve data từ table. khi một câu query được thực hiện, postgres sẽ kiểm tra xem indexes

0 0 23

- vừa được xem lúc

Setup cho dự án NestJS - Phần 10: Indexes trong MongoDB 📑

Đây là bài viết nằm trong Series NestJS thực chiến, các bạn có thể xem toàn bộ bài viết ở link: https://viblo.asia/s/nestjs-thuc-chien-MkNLr3kaVgA.

0 0 27