Giải thích MySQL EXPLAIN: Cách Đọc Kế Hoạch Thực Thi và Tối Ưu Hóa Truy Vấn SQL

目次

1. MySQL EXPLAIN là gì? Tại sao bạn nên sử dụng nó?

EXPLAIN là gì? Một lệnh để hiển thị kế hoạch thực thi

Trong MySQL, EXPLAIN là một lệnh được dùng để trực quan hoá cách một truy vấn SQL được thực thi. Nó đặc biệt hữu ích để hiểu cách dữ liệu được truy xuất trong các câu lệnh SELECT, và nó hiển thị kế hoạch thực thi của truy vấn.

Ví dụ, khi thực thi một truy vấn như SELECT * FROM users WHERE age > 30, EXPLAIN cho phép bạn xem các chi tiết nội bộ như chỉ mục nào MySQL đang sử dụng và thứ tự các bảng được quét như thế nào.

Cách sử dụng rất đơn giản — chỉ cần thêm EXPLAIN vào đầu câu truy vấn của bạn.

EXPLAIN SELECT * FROM users WHERE age > 30;

Khi viết theo cách này, nhiều cột mô tả kế hoạch thực thi truy vấn sẽ được hiển thị. Mỗi mục sẽ được giải thích chi tiết trong các phần sau.

Tại sao bạn nên sử dụng: Làm cho nguyên nhân truy vấn chậm hiện ra

Một sai lầm phổ biến mà nhiều nhà phát triển mắc phải là cho rằng “nếu SQL chạy, không có vấn đề gì”. Tuy nhiên, việc thực thi truy vấn chậm có thể ảnh hưởng tiêu cực đến hiệu năng tổng thể của ứng dụng.

Trong các hệ thống xử lý khối lượng dữ liệu lớn, ngay cả một truy vấn không hiệu quả duy nhất cũng có thể trở thành nút thắt cổ chai và gây tải đáng kể cho máy chủ.

Đó là lúc EXPLAIN trở nên cực kỳ hữu ích. Bằng cách xem xét kế hoạch thực thi, bạn có thể thấy rõ liệu có đang thực hiện quét toàn bộ bảng hay các chỉ mục đã được sử dụng đúng cách hay chưa.

Nói cách khác, việc sử dụng EXPLAIN cho phép bạn xác định các nút thắt hiệu năng và quyết định cách tối ưu chúng. Hiệu quả của chỉ mục, đặc biệt, trở nên rõ ràng hơn khi phân tích đầu ra của EXPLAIN.

Các câu lệnh SQL được EXPLAIN hỗ trợ (SELECT, UPDATE, v.v.)

EXPLAIN không chỉ hoạt động với các câu lệnh SELECT mà còn với các câu lệnh SQL sau đây:

  • SELECT
  • DELETE
  • INSERT
  • REPLACE
  • UPDATE

Ví dụ, khi chạy một câu lệnh DELETE trên một tập dữ liệu lớn, nếu các chỉ mục không được sử dụng đúng cách, MySQL có thể thực hiện quét toàn bộ bảng, làm tăng đáng kể thời gian thực thi. Để ngăn ngừa các vấn đề này, việc kiểm tra kế hoạch thực thi bằng EXPLAIN trước khi chạy các câu lệnh DELETE hoặc UPDATE là rất hiệu quả.

Tùy thuộc vào phiên bản MySQL của bạn, bạn cũng có thể sử dụng EXPLAIN ANALYZE, cung cấp thông tin thực thi chi tiết hơn nữa. Phần này sẽ được đề cập sau trong bài viết.

2. Hiểu các cột đầu ra của EXPLAIN (kèm hình minh họa)

Danh sách và giải thích các cột đầu ra cơ bản

Kết quả EXPLAIN bao gồm các cột sau (có thể hơi khác nhau tùy phiên bản MySQL):

Column NameDescription
idIdentifier indicating execution order or grouping within the query
select_typeThe type of SELECT (e.g., subquery, UNION)
tableName of the table being accessed
typeJoin type (access method)
possible_keysPossible indexes that could be used
keyActual index used
key_lenLength of the used index (in bytes)
refValue compared against the index
rowsEstimated number of rows MySQL expects to scan
ExtraAdditional details (sorting, temporary tables, etc.)

Trong số này, bốn cột quan trọng nhất cho việc tối ưu hiệu năng là type / key / rows / Extra.

Cách đọc bốn cột quan trọng: type / key / rows / Extra

1. type (Phương thức truy cập)

Cột này cho biết MySQL truy cập bảng như thế nào. Nó ảnh hưởng trực tiếp đến hiệu năng.

Example ValueMeaningPerformance Level
ALLFull table scan✕ Slow
indexFull index scan△ Moderate
rangeRange scan○ Good
ref / eq_refIndex lookup◎ Excellent
const / systemSingle-row access◎ Very Fast

Nếu type = ALL, nghĩa là không có chỉ mục nào được sử dụng và tất cả các hàng đều được quét — phương thức truy cập chậm nhất. Lý tưởng nhất, bạn nên tối ưu truy vấn về phía ref hoặc const.

2. key (Chỉ mục được sử dụng)

Cột này hiển thị tên của chỉ mục thực sự được dùng.
Nếu không có gì hiển thị, truy vấn có khả năng không sử dụng chỉ mục.

3. rows (Số hàng ước tính sẽ quét)

Cột này cho biết MySQL ước tính sẽ quét bao nhiêu hàng. Số càng lớn, thời gian thực thi thường càng dài. Mục tiêu là tối ưu truy vấn sao cho rows càng gần 1 càng tốt.

4. Extra (Thông tin bổ sung)

Cột Extra bao gồm các chi tiết bổ sung như các thao tác sắp xếp hoặc việc sử dụng bảng tạm thời.

Extra ExampleMeaningOptimization Hint
Using temporaryTemporary table used (performance degradation)Review GROUP BY / ORDER BY
Using filesortManual sorting operation performedAdd index-based sorting
Using indexData retrieved using only the index (fast)○ Good state

Nếu bạn thấy Using temporary hoặc Using filesort, nên xem xét lại câu lệnh SQL hoặc thiết kế chỉ mục của mình.

[Illustration] Ví dụ đầu ra EXPLAIN

EXPLAIN SELECT * FROM users WHERE age > 30;
idselect_typetabletypepossible_keyskeykey_lenrefrowsExtra
1SIMPLEusersALLage_indexNULLNULLNULL5000Using where

Trong ví dụ này, mặc dù chỉ mục (age_index) tồn tại, nó không thực sự được sử dụng, dẫn đến ALL (quét toàn bộ bảng). Điều này cho thấy còn chỗ để tối ưu hoá.

3. Học qua ví dụ: Cách sử dụng EXPLAIN và giải thích kết quả

Ví dụ 1: Kết quả EXPLAIN cho một truy vấn SELECT đơn giản (Có giải thích)

Hãy bắt đầu với một truy vấn SELECT đơn giản trên một bảng duy nhất.

EXPLAIN SELECT * FROM users WHERE age > 30;

Giả sử kết quả EXPLAIN trông như sau:

idselect_typetabletypepossible_keyskeykey_lenrefrowsExtra
1SIMPLEusersALLageNULLNULLNULL5000Using where

Giải thích:

  • type: ALL → Quét toàn bộ bảng. Không có chỉ mục nào được sử dụng.
  • key: NULL → Không có chỉ mục nào thực sự được dùng.
  • rows: 5000 → MySQL ước tính sẽ quét khoảng 5.000 hàng.

Cách cải thiện:

Bằng cách thêm một chỉ mục vào cột age, bạn có thể cải thiện đáng kể hiệu suất truy vấn.

CREATE INDEX idx_age ON users(age);

Nếu bạn chạy lại EXPLAIN, bạn sẽ thấy type thay đổi thành range hoặc ref, xác nhận rằng chỉ mục hiện đã được sử dụng.

Ví dụ 2: Phân tích kết quả EXPLAIN cho một truy vấn có JOIN

Tiếp theo, hãy xem một ví dụ mà JOIN nhiều bảng.

EXPLAIN
SELECT orders.id, users.name
FROM orders
JOIN users ON orders.user_id = users.id
WHERE users.age > 30;

Kết quả ví dụ:

idselect_typetabletypepossible_keyskeykey_lenrefrowsExtra
1SIMPLEusersALLPRIMARY, ageNULLNULLNULL3000Using where
1SIMPLEordersrefuser_iduser_id4users.id5Using index

Giải thích:

  • Bảng users đang thực hiện quét toàn bộ (ALL), vì vậy đây là phần cần cải thiện.
  • Trong khi đó, bảng orders sử dụng một chỉ mục với ref, điều này hiệu quả.

Các điểm tối ưu hóa:

  • Thêm một chỉ mục trên users.age có thể tăng tốc việc quét bảng users.
  • Điều quan trọng là thiết kế các chỉ mục sao cho mệnh đề WHERE có thể lọc các hàng trước khi thực hiện JOIN.

Khi các chỉ mục không được sử dụng (Ví dụ xấu → Ví dụ tốt)

Ví dụ xấu: Mệnh đề WHERE sử dụng hàm

SELECT * FROM users WHERE DATE(created_at) = '2024-01-01';

Với một truy vấn như vậy, chỉ mục trở nên không sử dụng được vì hàm DATE() biến đổi giá trị cột, ngăn MySQL sử dụng chỉ mục một cách hiệu quả.

Ví dụ cải thiện: chỉ định một phạm vi mà không dùng hàm

SELECT * FROM users
WHERE created_at >= '2024-01-01' AND created_at < '2024-01-02';

Điều này cho phép chỉ mục trên cột created_at được sử dụng, giúp MySQL truy xuất dữ liệu một cách hiệu quả.

Kết luận: Sử dụng các ví dụ EXPLAIN thực tế để chẩn đoán hiệu suất

Bằng cách phân tích kết quả EXPLAIN trong các truy vấn thực tế, bạn có thể xác định rõ điểm nghẽn và cách tối ưu chúng.

  • ALL → Quét toàn bộ. Cân nhắc thêm hoặc điều chỉnh chỉ mục.
  • key = NULL → Chỉ mục không được sử dụng. Cần điều tra.
  • Extra chứa Using temporary → Cảnh báo hiệu suất.
  • Sử dụng hàm hoặc phép tính trong điều kiện có thể vô hiệu hoá việc sử dụng chỉ mục.

Giữ những điểm này trong tâm trí sẽ giúp bạn liên tục cải thiện hiệu suất truy vấn với EXPLAIN.

4. Kỹ thuật tối ưu hoá truy vấn thực tế dựa trên kết quả EXPLAIN

Các nguyên tắc cơ bản thiết kế chỉ mục để tránh “type: ALL”

Nếu EXPLAIN hiển thị type: ALL, nghĩa là MySQL đang thực hiện quét toàn bộ bảng. Đây là một thao tác rất tốn kém, và trở thành nút thắt chính cho các bảng chứa hàng nghìn đến hàng triệu dòng.

Cách tránh điều này:

  • Thêm chỉ mục vào các cột được sử dụng trong mệnh đề WHERE
    CREATE INDEX idx_age ON users(age);
    
  • Nếu bạn có nhiều điều kiện, hãy cân nhắc chỉ mục tổng hợp
    CREATE INDEX idx_status_created ON orders(status, created_at);
    
  • Tránh các mẫu LIKE không bắt đầu bằng tiền tố
    -- Bad example (index won’t work)
    WHERE name LIKE '%tanaka%'
    
    -- Good example (index may work)
    WHERE name LIKE 'tanaka%'
    

Ý nghĩa của “Extra: Using temporary” và cách khắc phục

Nếu cột Extra hiển thị “Using temporary”, nghĩa là MySQL đang tạo một bảng tạm thời nội bộ để xử lý truy vấn. Điều này thường xảy ra khi các thao tác như GROUP BY hoặc ORDER BY không thể được xử lý chỉ bằng chỉ mục, vì vậy MySQL phải sử dụng bộ nhớ tạm để sắp xếp dữ liệu một cách thủ công.

Cách khắc phục:

  • Áp dụng chỉ mục vào các cột được sử dụng trong GROUP BY và ORDER BY
    CREATE INDEX idx_group_col ON sales(department_id);
    
  • Xóa bỏ việc sắp xếp hoặc GROUP BY không cần thiết trong SQL của bạn
  • Sử dụng LIMIT hoặc các truy vấn con để giảm dữ liệu mục tiêu

Hiểu Những gì “rows” và “key” Nói với Bạn để Cải thiện Hiệu suất

Cột rows cho biết MySQL dự đoán cần đọc bao nhiêu hàng từ bảng. Ví dụ, một truy vấn hiển thị rows = 100000 có thể ảnh hưởng đáng kể đến hiệu suất.

Khi giá trị này lớn, bạn có thể cần áp dụng các chỉ mục để giảm số hàng được quét hoặc viết lại các điều kiện.

Ngược lại, cột key hiển thị chỉ mục thực sự được sử dụng. Nếu nó là NULL, đó là cảnh báo rằng không có chỉ mục nào được dùng.

Danh sách kiểm tra tối ưu hoá:

  • Nếu rows lớn → Bộ lọc của bạn có hiệu quả không? Các chỉ mục có được sử dụng đúng cách không?
  • Nếu key = NULL → Bạn có đang sử dụng các mẫu trong WHERE/JOIN khiến không thể sử dụng chỉ mục không?

Biến EXPLAIN và Tối ưu hoá thành Thói quen

Để tinh chỉnh các truy vấn một cách hiệu quả, cách tiếp cận cơ bản là lặp lại chu kỳ này: viết → kiểm tra bằng EXPLAIN → cải thiện → kiểm tra lại.

Hãy ghi nhớ quy trình làm việc này:

  1. Viết truy vấn một cách bình thường
  2. Kiểm tra kế hoạch thực thi bằng EXPLAIN
  3. Xem lại type, key, rowsExtra
  4. Nếu có nút thắt, sửa đổi chỉ mục hoặc viết lại truy vấn
  5. Chạy lại EXPLAIN để xác nhận các cải tiến

Hiệu suất truy vấn không chỉ bị ảnh hưởng bởi các chỉ mục mà còn bởi cách viết truy vấn. Các phép so sánh đơn giản (thay vì hàm) và các điều kiện thẳng thắn có thể hiệu quả một cách bất ngờ.

5. Phân tích Trực quan với MySQL Workbench Visual EXPLAIN

Kiểm tra Kế hoạch Thực thi một cách Trực quan bằng Công cụ GUI

MySQL Workbench là một công cụ GUI chuyên dụng cho việc quản trị và phát triển MySQL. Một trong những ưu điểm lớn nhất của nó là có thể hiển thị kế hoạch thực thi một cách trực quan, điều mà thường khó đọc trong đầu ra của terminal.

Với Visual EXPLAIN, bạn có thể xem lại các thông tin sau trong một cấu trúc cây:

  • Thứ tự truy cập của mỗi bảng
  • Kiểu JOIN được sử dụng
  • Trạng thái sử dụng chỉ mục
  • Có đang thực hiện quét toàn bộ bảng hay không
  • Các thao tác lọc và sắp xếp dữ liệu

Vì kế hoạch được hiển thị dưới dạng đồ họa, ngay cả người mới bắt đầu cũng có thể dễ dàng xác định nơi tồn tại các nút thắt hiệu suất.

[With Images] Cách Sử dụng và Đọc Visual EXPLAIN (Bước từng Bước)

Thực hiện các bước sau để sử dụng Visual EXPLAIN:

  1. Khởi chạy MySQL Workbench và mở kết nối cơ sở dữ liệu của bạn → Đảm bảo kết nối đã được cấu hình trước.
  2. Nhập truy vấn mục tiêu của bạn vào trình soạn thảo SQL
    SELECT * FROM users WHERE age > 30;
    
  1. Nhấn vào biểu tượng “EXPLAIN VISUAL” bên cạnh nút EXPLAIN → Hoặc nhấp chuột phải và chọn “Visual Explain” từ menu.
  2. Kế hoạch thực thi sẽ được hiển thị một cách trực quan Khi bạn nhấp vào mỗi nút (bảng), thông tin chi tiết như sau sẽ xuất hiện:
  • Phương pháp truy cập (ALL, ref, range, v.v.)
  • Chỉ mục được sử dụng
  • Số hàng ước tính (rows)
  • Điều kiện lọc và phương pháp JOIN

Lưu ý:
Trong Visual EXPLAIN, màu sắc và biểu tượng của các nút giúp làm nổi bật các thao tác nặng hoặc phần không hiệu quả.
Chú ý đặc biệt đến các nút được tô màu đỏ, vì chúng thường chỉ ra các vấn đề về hiệu suất.

Ngay cả Người Mới Bắt Đầu Cũng Có Thể Dễ Dàng Tìm Thấy Các Nút Thắt

Kết quả EXPLAIN dạng văn bản có thể gây choáng ngợp lúc đầu, nhưng Visual EXPLAIN làm cho các khu vực vấn đề nổi bật một cách trực quan.

Ví dụ, việc xác định trở nên dễ dàng hơn:

  • Các bảng sử dụng type: ALL
  • Các khối truy vấn hiển thị Using temporary
  • Các mẫu có JOIN không cần thiết
  • Các bảng mà chỉ mục không được sử dụng

Với giao diện GUI, bạn có thể nhanh chóng hình thành các giả thuyết tối ưu hoá, và nó cũng hữu ích cho việc chia sẻ và đánh giá hiệu suất SQL trong nhóm.

Visual EXPLAIN đặc biệt có giá trị cho người dùng SQL từ mới bắt đầu đến trung cấp.
Nếu bạn không chắc cách diễn giải kết quả EXPLAIN, hãy thử sử dụng tính năng này.

6. Câu hỏi Thường gặp (FAQ)

Q1. Khi nào tôi nên sử dụng EXPLAIN?

A. Bạn nên sử dụng EXPLAIN bất cứ khi nào bạn cảm thấy không chắc về tốc độ thực thi của một truy vấn — đặc biệt nếu một truy vấn “cảm thấy chậm”. Nó cũng hữu ích khi bạn muốn xác minh liệu một truy vấn mới tạo có sử dụng chỉ mục đúng cách hay không.

Bằng cách kiểm tra kế hoạch thực thi trước khi triển khai, bạn có thể xác định rủi ro hiệu năng sớm.

Q2. Kết quả hiển thị type = ALL. Tôi nên làm gì?

A. type: ALL có nghĩa là MySQL đang thực hiện quét toàn bộ bảng. Đây là một thao tác tốn kém và có thể làm giảm hiệu năng đáng kể, đặc biệt trên các bảng lớn.

Hãy cân nhắc các hành động sau:

  • Thêm chỉ mục vào các cột được sử dụng trong mệnh đề WHERE
  • Tránh các hàm hoặc thao tác làm vô hiệu hoá việc sử dụng chỉ mục
  • Tránh SELECT * và chỉ lấy các cột cần thiết

Q3. “Using temporary” trong cột Extra có phải là vấn đề không?

A. Using temporary cho biết MySQL đang tạo một bảng tạm nội bộ để xử lý truy vấn. Điều này thường xảy ra với GROUP BY hoặc ORDER BY, và có thể làm tăng chi phí bộ nhớ và I/O đĩa.

Các giải pháp khả thi bao gồm:

  • Thêm chỉ mục vào các cột được sử dụng trong GROUP BY / ORDER BY
  • Giảm việc sắp xếp hoặc tổng hợp không cần thiết
  • Sử dụng LIMIT hoặc các truy vấn con để giảm tập dữ liệu

Q4. Làm sao để sử dụng Visual EXPLAIN?

A. Bạn có thể sử dụng công cụ chính thức của MySQL “MySQL Workbench” để hiển thị kết quả EXPLAIN một cách trực quan trong giao diện GUI. Chỉ cần nhập truy vấn của bạn và nhấn nút “Visual Explain”.

Điều này đặc biệt được khuyến nghị cho:

  • Người dùng cảm thấy đầu ra EXPLAIN dạng văn bản khó đọc
  • Những người muốn hiểu trực quan các JOIN phức tạp
  • Các nhóm đánh giá hiệu năng SQL cùng nhau

Q5. Tại sao chỉ mục của tôi không được sử dụng mặc dù đã tồn tại?

A. Ngay cả khi một chỉ mục đã tồn tại, MySQL không phải lúc nào cũng sử dụng nó. Các chỉ mục có thể bị bỏ qua trong các trường hợp như:

  • Sử dụng hàm hoặc biểu thức trong mệnh đề WHERE (ví dụ, WHERE YEAR(created_at) = 2024 )
  • Độ đa trị thấp (phân bố giá trị thấp), khi quét toàn bộ được coi là nhanh hơn
  • Thứ tự cột không khớp với định nghĩa chỉ mục tổng hợp

Để xác nhận liệu một chỉ mục có được sử dụng đúng cách hay không, luôn kiểm tra cột key trong EXPLAIN.

7. Summary: Use EXPLAIN to Discover SQL Optimization Opportunities

Việc tối ưu hiệu năng trong MySQL không chỉ là thêm chỉ mục.
Công cụ thiết yếu để xác định truy vấn nào là nút thắt, tại sao chúng chậm và cách khắc phục là EXPLAIN.

Trong bài viết này, chúng tôi đã đề cập đến các điểm chính sau:

✅ The Role and Basic Usage of EXPLAIN

  • Chỉ cần thêm EXPLAIN trước một truy vấn để kiểm tra kế hoạch thực thi
  • Các vấn đề như quét toàn bộ (ALL) và Using temporary sẽ được hiển thị

✅ How to Read Output Columns and Evaluate Performance

  • Bốn cột quan trọng nhất là type, key, rowsExtra
  • Tránh quét toàn bộ bảng và hướng tới việc sử dụng chỉ mục đúng cách
  • Cẩn thận khi thấy Using temporary hoặc Using filesort

✅ Practical Diagnosis and Optimization Through Real Examples

  • Không chỉ thêm chỉ mục, mà cải thiện cú pháp SQL cũng quan trọng
  • Ngay cả các truy vấn phức tạp có JOIN hoặc truy vấn con cũng có thể được phân tích bằng EXPLAIN
  • Liên tục tinh chỉnh truy vấn dựa trên kế hoạch thực thi là cách nhanh nhất để cải thiện hiệu năng

✅ Use GUI Tools for Visual Confirmation

  • Sử dụng “Visual EXPLAIN” trong MySQL Workbench để xem kế hoạch thực thi dưới dạng đồ họa
  • Dễ dàng hơn cho người mới bắt đầu xác định các nút thắt một cách trực quan
  • Hữu ích cho các buổi thảo luận nhóm và đánh giá hiệu năng SQL

✅ FAQ Coverage for Real-World Scenarios

  • Giải thích nguyên nhân và giải pháp cho các vấn đề như type=ALL và key=NULL
  • Cung cấp ví dụ về lý do tại sao chỉ mục có thể không được sử dụng

✍️ Make EXPLAIN a Habit to Improve Your SQL Skills

Nếu bạn xây dựng thói quen kiểm tra truy vấn bằng EXPLAIN mỗi khi viết SQL, bạn sẽ tự nhiên bắt đầu viết các truy vấn nhanh hơn và hiệu quả hơn.

Đây không chỉ là một mẹo kỹ thuật — nó là một phần của việc phát triển năng lực SQL chuyên nghiệp.

  • Chạy EXPLAIN ngay sau khi viết một truy vấn
  • Sửa các kế hoạch thực thi đáng ngờ ngay lập tức
  • Thiết kế các chỉ mục hiệu quả một cách cân nhắc

Bằng cách nắm vững chu trình này, kỹ năng MySQL của bạn sẽ được cải thiện dần dần.

Chúng tôi hy vọng bài viết này sẽ là bước đầu tiên của bạn hướng tới việc tối ưu hoá truy vấn tốt hơn.

Nếu bạn có câu hỏi hoặc muốn chúng tôi đề cập thêm các chủ đề, hãy thoải mái để lại bình luận!