Hiểu về Clustered index

Chắc hẳn bạn đã từng nghe qua hai loại index là Clustered Index và Non-clustered index. Trên Google, bạn có thể tìm thấy một cách phân biệt đơn giản, đó là Clustered index được tạo trên một bảng với primary key, trong khi non-clustered index đơn giản là cho các key khác không phải là primary key. Tuy nhiên, liệu mô tả này có đủ thuyết phục hay không? Trong bài viết này, tôi sẽ giới thiệu cách hiểu của mình về clustered index và non-clustered index.

Clustered index

Clustered index là gì? Đơn giản là loại index xác định thứ tự lưu trữ dữ liệu vật lý trong một bảng. Bình thường, khi bạn tạo index cho một trường trong bảng, các giá trị của trường đó sẽ được tổ chức lưu trữ có cấu trúc (thông thường là sử dụng B-Tree), kết quả tìm kiếm trên B-Tree index sẽ chỉ trả về con trỏ tới bản ghi bạn đang tìm kiếm.

Tuy nhiên, với clustered index, toàn bộ bản ghi sẽ được lưu trữ trực tiếp trên B-Tree index. Sau khi tìm kiếm trên trường được đánh clustered index trên B-Tree, kết quả trả về chính là bản ghi bạn muốn tìm kiếm.

Có một lưu ý là toàn bộ dữ liệu của một bản ghi sẽ được lưu trên các nút lá của B-Tree, còn những nút trung gian chỉ lưu trữ giá trị của cột được đánh index. Một bảng chỉ nên có một clustered index, vì clustered index lưu trữ toàn bộ dữ liệu trong một bản ghi và bạn không nên lưu dữ liệu này ở nhiều nơi cùng một lúc.

Clustered index trên InnoDB

Không phải storage engine nào cũng hỗ trợ clustered index. Trong bài viết này, tôi sẽ tập trung nói về việc thực thi clustered index trên InnoDB, trong khi các storage engine khác có thể có các cách thực thi khác nhau, nguyên tắc hoạt động vẫn tương tự.

Có Thể Bạn Quan Tâm :   “Đảng viên 76” tâm huyết, trách nhiệm trong xây dựng đô thị văn minh ở thị trấn Thạch Hà

Trong InnoDB, mặc định, cột được đánh primary key cũng là cột “index column” cho việc cluster dữ liệu. Chính vì lý do này, bạn thường nghe nói “Clustered index được tạo ra trên một bảng với primary key”.

Tuy nhiên, nếu trong một bảng mà bạn không đánh primary key, thì bạn phải chọn cột nào để tạo clustered index. InnoDB sẽ lựa chọn cột theo một thứ tự ưu tiên như sau:

  • Trước tiên, InnoDB sẽ mặc định chọn Primary Key làm “index column”
  • Nếu bảng không có khai báo Primary key, InnoDB sẽ tìm kiếm cột thỏa mãn điều kiện Unique và Not null để tạo index
  • Nếu trong bảng không có cột nào Unique và Not null, InnoDB sẽ tự định nghĩa một hidden primary key và cluster dữ liệu trên cột này

Non-clustered index

Với cách lưu trữ index thông thường, dữ liệu sẽ được lưu trữ ở một vùng nhớ khác và các nút lá cuối cùng của B-Tree sẽ chứa con trỏ tới bản ghi cần tìm kiếm. Tuy nhiên, với clustered index, dữ liệu được tổ chức trực tiếp lưu trữ trên B-Tree. Primary key chính là “index column” được chọn để tạo clustering. Vậy cột khác khi được đánh index sẽ được lưu trữ như thế nào?

Trong InnoDB, tất cả các index khác không phải là clustered index sẽ chứa giá trị tương ứng với clustered index. Điều này có nghĩa là, khi bạn tìm kiếm với cột non-clustered index, hệ thống sẽ tìm kiếm trên B-Tree index của cột đó, kết quả trả về sẽ là clustered index tương ứng, sau đó hệ thống sẽ tiếp tục quét B-Tree của clustered index và trả về đầy đủ dữ liệu.

Ví dụ, nếu bạn có một bảng gồm ID, FName, LName. Trong đó ID là primary key, và bạn đánh index cho trường FName, sau đó InnoDB sẽ tạo hai B-Tree như sau

Hiểu về Clustered index

Khi thực hiện câu lệnh

select * from tables where FName = ?

Có Thể Bạn Quan Tâm :   Công thụ là gì? Ví dụ về công thủ

thì InnoDB sẽ tìm kiếm trên B-Tree của FName, sau khi tìm thấy node lá tương ứng, nó sẽ tiếp tục sử dụng giá trị của node lá này (chính là key của clustered index) để quét B-Tree của ID (clustered index) và trả về đầy đủ dữ liệu.

Lưu ý khi chọn cột để tạo clustered index

Việc sử dụng clustered index sẽ giúp tăng tốc độ truy cập dữ liệu. Vì clustered index lưu trữ index và dữ liệu trực tiếp trên B-Tree. Dữ liệu sẽ được trả về ngay sau khi quét B-Tree kết thúc, mà không cần tìm kiếm con trỏ như thông thường, từ đó cải thiện hiệu năng của các tải công việc liên quan đến I/O.

Tuy nhiên, nếu sử dụng không đúng cách, clustered index sẽ làm giảm hiệu suất:

  • Tốc độ chèn vào cluster phụ thuộc vào vị trí muốn chèn. Vì bản chất của index là lưu trữ có thứ tự, khi chèn một bản ghi mới, bạn sẽ phải tìm vị trí phù hợp để chèn thay vì chèn vào một vị trí ô nhớ khả dụng kế tiếp như thông thường.
  • Chi phí để cập nhật cột được tạo clustered index rất đắt, vì InnoDB cũng phải di chuyển toàn bộ bản ghi tương ứng đến vị trí mới.
  • Bảng sử dụng clustered index có thể bị phân trang khi bản ghi mới được chèn vào hoặc khi cột được đánh index được cập nhật. Phân trang xảy ra khi một khóa sau khi tìm kiếm có vị trí sắp xếp đã đầy bắt buộc phải chèn vào vị trí trong trang dữ liệu đã đầy. Khi đó, bộ định vị lưu trữ phải chia trang này thành hai, và bảng sẽ sử dụng nhiều không gian ổ cứng hơn.
  • Chính việc có thể phải phân trang như trên, các bảng được sắp xếp có thể chậm hơn khi thực hiện quét toàn bộ bảng.
  • Kích thước của non-clustered index có thể lớn hơn thông thường, vì các nút lá của nó lưu trữ giá trị từ clustered index, và giá trị này càng lớn (ví dụ như kiểu varchar), thì non-clustered index càng lớn.

Vậy, làm thế nào để sử dụng clustered index đúng cách và tránh những hạn chế đã nêu ở trên?

Có Thể Bạn Quan Tâm :   Quan hệ pháp luật dân sự là gì? Đặc điểm, thành phần quan hệ pháp luật dân sự?

Câu trả lời là bạn nên sử dụng trường AUTO INCREMENT cho cột được chọn để tạo clustered index. Vì sao? Hãy so sánh việc chọn một trường AUTO INCREMENT và một trường có giá trị ngẫu nhiên thỏa mãn UNIQUE và NOT NULL (ví dụ như UUID) làm clustered index, và phân tích hiệu suất của hai trường hợp này tương ứng với các hạn chế đã nêu ở trên.

Trường clustered index AUTO INCREMENT trường column Random Chi phí chèn Với key tự động tăng, bản ghi mới chỉ cần chèn vào cuối cùng. Việc tìm vị trí phù hợp để chèn key và bản ghi Với key ngẫu nhiên, bản ghi mới có thể chèn vào một vị trí ngẫu nhiên, dẫn đến phân trang chiếm dụng nhiều không gian Chi phí cập nhật Không nên cập nhật cột đã đánh clustered index để tránh việc này Không nên cập nhật cột đã đánh clustered index để tránh việc này Hạn chế phân trang Với trường tự động tăng, bản ghi mới luôn được chèn vào cuối cùng, không có trường hợp chèn vào giữa những vị trí đã có dữ liệu, do đó storage engine không cần phải phân trang lãng phí. Vì record mới sẽ được chèn vào ngẫu nhiên, dẫn đến phân trang chiếm dụng nhiều không gian. Giảm kích thước của non-clustered index Thông thường, trường tự động tăng sẽ có kiểu dữ liệu Number, nhỏ hơn nhiều so với varchar, nếu kiểu dữ liệu là varchar và có kích thước lớn, thì non-clustered index sẽ phải tốn nhiều không gian hơn để lưu giá trị đó.

Từ những so sánh này, bạn có thể thấy rằng, khi tạo clustered index, bạn nên chọn trường UNIQUE, NOT NULL và AUTO INCREMENT để có hiệu suất tốt nhất. Thông thường, cột đó chính là cột ID được khai báo là Primary Key, và InnoDB sẽ tự động chọn nó làm clustered index.

Hy vọng qua bài viết, bạn đã hiểu rõ hơn về bản chất của clustered index thay vì chỉ xem nó như “Clustered index được tạo trên một bảng với primary key”.

You May Also Like

About the Author: admin