Bài viết sau dịch từ nguồn sitepoint.com.
Khi bạn muốn thực thi một câu truy vấn [query], MySQL Query Optimizer sẽ cố gắng đưa ra một kế hoạch tối ưu nhất cho việc thực hiện query. Bạn có thể thấy thông tin về kế hoạch đó bằng cách thêm lệnh
********************** 1. row **********************
id: 1
select_type: SIMPLE
table: categories
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
Extra:
1 row in set [0.00 sec]
5 vào đầu mỗi query. ********************** 1. row **********************
id: 1
select_type: SIMPLE
table: categories
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
Extra:
1 row in set [0.00 sec]
5 là một trong những công cụ quan trọng giúp hiểu và tối ưu truy vấn MySQL, tuy nhiên, điều đáng tiếc là rất nhiều lập trình viên hiếm khi dùng nó. Trong bài viết này, bạn sẽ được học ý nghĩa từng thành phần trong kết quả trả về của ********************** 1. row **********************
id: 1
select_type: SIMPLE
table: categories
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
Extra:
1 row in set [0.00 sec]
5 và cách dùng nó để tối ưu thiết kế cơ sở dữ liệu cũng như câu truy vấn.Tìm hiểu kết quả trả về của lệnh ********************** 1. row **********************
id: 1
select_type: SIMPLE
table: categories
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
Extra:
1 row in set [0.00 sec]
5
********************** 1. row **********************
id: 1
select_type: SIMPLE
table: categories
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
Extra:
1 row in set [0.00 sec]
Việc sử dụng
********************** 1. row **********************
id: 1
select_type: SIMPLE
table: categories
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
Extra:
1 row in set [0.00 sec]
5 hết sức đơn giản, chỉ cần thêm nó vào trước EXPLAIN EXTENDED SELECT City.Name FROM City
JOIN Country ON [City.CountryCode = Country.Code]
WHERE City.CountryCode = 'IND' AND Country.Continent = 'Asia'\G
0 trong câu truy vấn. Trước tiên hãy cùng tìm hiểu kết quả trả về của một câu truy vấn đơn giản để bạn có thể làm quen với các cột trong bảng kết quả.EXPLAIN SELECT * FROM categories\G
********************** 1. row **********************
id: 1
select_type: SIMPLE
table: categories
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
Extra:
1 row in set [0.00 sec]
Có rất nhiều thông tin được bao hàm trong 10 cột trên. Đó là:
1 - Số thứ tự cho mỗi câuEXPLAIN EXTENDED SELECT City.Name FROM City JOIN Country ON [City.CountryCode = Country.Code] WHERE City.CountryCode = 'IND' AND Country.Continent = 'Asia'\G
0 trong truy vấn của bạn [trường hợp bạn sử dụng các truy vấn lồng nhau [nested subqueries].EXPLAIN EXTENDED SELECT City.Name FROM City JOIN Country ON [City.CountryCode = Country.Code] WHERE City.CountryCode = 'IND' AND Country.Continent = 'Asia'\G
3 - Loại của câuEXPLAIN EXTENDED SELECT City.Name FROM City JOIN Country ON [City.CountryCode = Country.Code] WHERE City.CountryCode = 'IND' AND Country.Continent = 'Asia'\G
0. Có thể có các giá trị sau.EXPLAIN EXTENDED SELECT City.Name FROM City JOIN Country ON [City.CountryCode = Country.Code] WHERE City.CountryCode = 'IND' AND Country.Continent = 'Asia'\G
5 - Truy vấn là một câuEXPLAIN EXTENDED SELECT City.Name FROM City JOIN Country ON [City.CountryCode = Country.Code] WHERE City.CountryCode = 'IND' AND Country.Continent = 'Asia'\G
0 cơ bản, không có bất cứ truy vấn con [subqueries] hay câu lệnh hợp [EXPLAIN EXTENDED SELECT City.Name FROM City JOIN Country ON [City.CountryCode = Country.Code] WHERE City.CountryCode = 'IND' AND Country.Continent = 'Asia'\G
7] nào.EXPLAIN EXTENDED SELECT City.Name FROM City JOIN Country ON [City.CountryCode = Country.Code] WHERE City.CountryCode = 'IND' AND Country.Continent = 'Asia'\G
8 - Truy vấn là câuEXPLAIN EXTENDED SELECT City.Name FROM City JOIN Country ON [City.CountryCode = Country.Code] WHERE City.CountryCode = 'IND' AND Country.Continent = 'Asia'\G
0 ngoài cùng của một lệnhEXPLAIN EXTENDED SELECT City.Name FROM City JOIN Country ON [City.CountryCode = Country.Code] WHERE City.CountryCode = 'IND' AND Country.Continent = 'Asia'\G
0.********************** 1. row ********************** id: 1 select_type: SIMPLE table: Country type: const possible_keys: PRIMARY key: PRIMARY key_len: 3 ref: const rows: 1 filtered: 100.00 Extra: ********************** 2. row ********************** id: 1 select_type: SIMPLE table: City type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 4079 filtered: 100.00 Extra: Using where 2 rows in set, 1 warning [0.00 sec]
1 - Truy vấn là một truy vấn con của truy vấn khác, nằm trong lệnh********************** 1. row ********************** id: 1 select_type: SIMPLE table: Country type: const possible_keys: PRIMARY key: PRIMARY key_len: 3 ref: const rows: 1 filtered: 100.00 Extra: ********************** 2. row ********************** id: 1 select_type: SIMPLE table: City type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 4079 filtered: 100.00 Extra: Using where 2 rows in set, 1 warning [0.00 sec]
2.********************** 1. row ********************** id: 1 select_type: SIMPLE table: Country type: const possible_keys: PRIMARY key: PRIMARY key_len: 3 ref: const rows: 1 filtered: 100.00 Extra: ********************** 2. row ********************** id: 1 select_type: SIMPLE table: City type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 4079 filtered: 100.00 Extra: Using where 2 rows in set, 1 warning [0.00 sec]
3 - Truy vấn đầu tiên của một truy vấn con.********************** 1. row ********************** id: 1 select_type: SIMPLE table: Country type: const possible_keys: PRIMARY key: PRIMARY key_len: 3 ref: const rows: 1 filtered: 100.00 Extra: ********************** 2. row ********************** id: 1 select_type: SIMPLE table: City type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 4079 filtered: 100.00 Extra: Using where 2 rows in set, 1 warning [0.00 sec]
4 - Truy vấn con, phụ thuộc vào một truy vấn khác bên ngoài nó.********************** 1. row ********************** id: 1 select_type: SIMPLE table: Country type: const possible_keys: PRIMARY key: PRIMARY key_len: 3 ref: const rows: 1 filtered: 100.00 Extra: ********************** 2. row ********************** id: 1 select_type: SIMPLE table: City type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 4079 filtered: 100.00 Extra: Using where 2 rows in set, 1 warning [0.00 sec]
5 - Truy vấn không thể lưu lại được [có quy định điều kiện cụ thể, thế nào là một truy vấn có thể lưu lại được].********************** 1. row ********************** id: 1 select_type: SIMPLE table: Country type: const possible_keys: PRIMARY key: PRIMARY key_len: 3 ref: const rows: 1 filtered: 100.00 Extra: ********************** 2. row ********************** id: 1 select_type: SIMPLE table: City type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 4079 filtered: 100.00 Extra: Using where 2 rows in set, 1 warning [0.00 sec]
7 - Truy vấn là câuEXPLAIN EXTENDED SELECT City.Name FROM City JOIN Country ON [City.CountryCode = Country.Code] WHERE City.CountryCode = 'IND' AND Country.Continent = 'Asia'\G
0 thứ hai của lệnhEXPLAIN EXTENDED SELECT City.Name FROM City JOIN Country ON [City.CountryCode = Country.Code] WHERE City.CountryCode = 'IND' AND Country.Continent = 'Asia'\G
7.EXPLAIN EXTENDED SELECT City.Name FROM City JOIN Country ON [City.CountryCode = Country.Code] WHERE City.CountryCode = 'IND' AND Country.Continent = 'Asia'\G
9 - Truy vấn thứ hai hoặc các truy vấn tiếp theo của lệnh********************** 1. row ********************** id: 1 select_type: SIMPLE table: Country type: const possible_keys: PRIMARY key: PRIMARY key_len: 3 ref: const rows: 1 filtered: 100.00 Extra: ********************** 2. row ********************** id: 1 select_type: SIMPLE table: City type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 4079 filtered: 100.00 Extra: Using where 2 rows in set, 1 warning [0.00 sec]
7 phụ thuộc vào một truy vấn bên ngoài.EXPLAIN EXTENDED SELECT City.Name FROM City JOIN Country ON [City.CountryCode = Country.Code] WHERE City.CountryCode = 'IND' AND Country.Continent = 'Asia'\G
1 - Truy vấn là kết quả của lệnhSHOW WARNINGS\G
7.EXPLAIN EXTENDED SELECT City.Name FROM City JOIN Country ON [City.CountryCode = Country.Code] WHERE City.CountryCode = 'IND' AND Country.Continent = 'Asia'\G
3 - Bảng liên quan đến câu truy vấn.SHOW WARNINGS\G
4 - Cách MySQL join các bảng lại với nhau. Đây là một trong những trường quan trọng nhất của kết quả trả về, nó chỉ ra đâu là nơi thiếu chỉ mục [index] và làm cách nào truy vấn của bạn cần phải xem xét lại. Các giá trị trả về có thể là.SHOW WARNINGS\G
5 - Bảng không có hoặc chỉ có 1 dòng.SHOW WARNINGS\G
6 - Bảng chỉ có duy nhất 1 dòng đã được đánh chỉ mục mà khớp với điều kiện tìm kiếm. Đây là loại join nhanh nhất, bởi bảng chỉ cần đọc một lần duy nhất và giá trị của cột được xem như là hằng số khi join với các bảng khác.SHOW WARNINGS\G
7 - Tất cả các thành phần của index được sử dụng bởi lệnh join và index thuộc loạiSHOW WARNINGS\G
8 hoặcSHOW WARNINGS\G
9. Đây là loại join tốt thứ hai [chỉ sauSHOW WARNINGS\G
6].SHOW WARNINGS\G
1 - Tất cả các dòng khớp với điều kiện tìm kiếm và chưa cột đã được index đều được đọc cho mỗi sự kết hợp với các dòng của bảng trước đó. Loại join này có thể thấy khi so sánh cột với điều kiện********************** 1. row ********************** Level: Note Code: 1003 Message: select `World`.`City`.`Name` AS `Name` from `World`.`City` join `World`.`Country` where [[`World`.`City`.`CountryCode` = 'IND']] 1 row in set [0.00 sec]
2 hoặc********************** 1. row ********************** Level: Note Code: 1003 Message: select `World`.`City`.`Name` AS `Name` from `World`.`City` join `World`.`Country` where [[`World`.`City`.`CountryCode` = 'IND']] 1 row in set [0.00 sec]
3.********************** 1. row ********************** Level: Note Code: 1003 Message: select `World`.`City`.`Name` AS `Name` from `World`.`City` join `World`.`Country` where [[`World`.`City`.`CountryCode` = 'IND']] 1 row in set [0.00 sec]
4 - join sử dụng chỉ mục dạng********************** 1. row ********************** Level: Note Code: 1003 Message: select `World`.`City`.`Name` AS `Name` from `World`.`City` join `World`.`Country` where [[`World`.`City`.`CountryCode` = 'IND']] 1 row in set [0.00 sec]
5.********************** 1. row ********************** Level: Note Code: 1003 Message: select `World`.`City`.`Name` AS `Name` from `World`.`City` join `World`.`Country` where [[`World`.`City`.`CountryCode` = 'IND']] 1 row in set [0.00 sec]
6 - Gần giống như********************** 1. row ********************** Level: Note Code: 1003 Message: select `World`.`City`.`Name` AS `Name` from `World`.`City` join `World`.`Country` where [[`World`.`City`.`CountryCode` = 'IND']] 1 row in set [0.00 sec]
1 nhưng chứa cả các dòng với cột mang giá trị null.********************** 1. row ********************** Level: Note Code: 1003 Message: select `World`.`City`.`Name` AS `Name` from `World`.`City` join `World`.`Country` where [[`World`.`City`.`CountryCode` = 'IND']] 1 row in set [0.00 sec]
8 - join sử dụng một danh sách các chỉ mục để tạo ra tập kết quả. Cột********************** 1. row ********************** Level: Note Code: 1003 Message: select `World`.`City`.`Name` AS `Name` from `World`.`City` join `World`.`Country` where [[`World`.`City`.`CountryCode` = 'IND']] 1 row in set [0.00 sec]
9 trong kết quả của********************** 1. row ********************** Level: Note Code: 1003 Message: select `World`.`City`.`Name` AS `Name` from `World`.`City` join `World`.`Country` where [[`World`.`City`.`CountryCode` = 'IND']] 1 row in set [0.00 sec]
5 sẽ liệt kê các khóa được sử dụng.********************** 1. row ********************** id: 1 select_type: SIMPLE table: categories type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 4 Extra: 1 row in set [0.00 sec]
1 - Truy vấn con với lệnhEXPLAIN SELECT * FROM orderdetails d INNER JOIN orders o ON d.orderNumber = o.orderNumber INNER JOIN products p ON p.productCode = d.productCode INNER JOIN productlines l ON p.productLine = l.productLine INNER JOIN customers c on c.customerNumber = o.customerNumber WHERE o.orderNumber = 10101\G
2 trả về duy nhất một kết quả và sử dụngEXPLAIN SELECT * FROM orderdetails d INNER JOIN orders o ON d.orderNumber = o.orderNumber INNER JOIN products p ON p.productCode = d.productCode INNER JOIN productlines l ON p.productLine = l.productLine INNER JOIN customers c on c.customerNumber = o.customerNumber WHERE o.orderNumber = 10101\G
3.EXPLAIN SELECT * FROM orderdetails d INNER JOIN orders o ON d.orderNumber = o.orderNumber INNER JOIN products p ON p.productCode = d.productCode INNER JOIN productlines l ON p.productLine = l.productLine INNER JOIN customers c on c.customerNumber = o.customerNumber WHERE o.orderNumber = 10101\G
4 - Gần giống nhưEXPLAIN SELECT * FROM orderdetails d INNER JOIN orders o ON d.orderNumber = o.orderNumber INNER JOIN products p ON p.productCode = d.productCode INNER JOIN productlines l ON p.productLine = l.productLine INNER JOIN customers c on c.customerNumber = o.customerNumber WHERE o.orderNumber = 10101\G
1 nhưng trả về nhiều hơn một dòng.EXPLAIN SELECT * FROM orderdetails d INNER JOIN orders o ON d.orderNumber = o.orderNumber INNER JOIN products p ON p.productCode = d.productCode INNER JOIN productlines l ON p.productLine = l.productLine INNER JOIN customers c on c.customerNumber = o.customerNumber WHERE o.orderNumber = 10101\G
6 - Chỉ mục được dùng để tìm ra các dòng thỏa mãn điều kiện tìm kiếm, cụ thể là khi khóa được so sánh với hằng số thông qua các toán tửEXPLAIN SELECT * FROM orderdetails d INNER JOIN orders o ON d.orderNumber = o.orderNumber INNER JOIN products p ON p.productCode = d.productCode INNER JOIN productlines l ON p.productLine = l.productLine INNER JOIN customers c on c.customerNumber = o.customerNumber WHERE o.orderNumber = 10101\G
7,EXPLAIN SELECT * FROM orderdetails d INNER JOIN orders o ON d.orderNumber = o.orderNumber INNER JOIN products p ON p.productCode = d.productCode INNER JOIN productlines l ON p.productLine = l.productLine INNER JOIN customers c on c.customerNumber = o.customerNumber WHERE o.orderNumber = 10101\G
2,EXPLAIN SELECT * FROM orderdetails d INNER JOIN orders o ON d.orderNumber = o.orderNumber INNER JOIN products p ON p.productCode = d.productCode INNER JOIN productlines l ON p.productLine = l.productLine INNER JOIN customers c on c.customerNumber = o.customerNumber WHERE o.orderNumber = 10101\G
9,EXPLAIN SELECT * FROM orderdetails d INNER JOIN orders o ON d.orderNumber = o.orderNumber INNER JOIN products p ON p.productCode = d.productCode INNER JOIN productlines l ON p.productLine = l.productLine INNER JOIN customers c on c.customerNumber = o.customerNumber WHERE o.orderNumber = 10101\G
0,...********************** 1. row ********************** id: 1 select_type: SIMPLE table: l type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 7 Extra: ********************** 2. row ********************** id: 1 select_type: SIMPLE table: p type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 110 Extra: Using where; Using join buffer ********************** 3. row ********************** id: 1 select_type: SIMPLE table: c type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 122 Extra: Using join buffer ********************** 4. row ********************** id: 1 select_type: SIMPLE table: o type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 326 Extra: Using where; Using join buffer ********************** 5. row ********************** id: 1 select_type: SIMPLE table: d type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 2996 Extra: Using where; Using join buffer 5 rows in set [0.00 sec]
1 - Toàn bộ cây chỉ mục được duyệt để tìm ra dòng thỏa mãn điều kiện.********************** 1. row ********************** id: 1 select_type: SIMPLE table: l type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 7 Extra: ********************** 2. row ********************** id: 1 select_type: SIMPLE table: p type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 110 Extra: Using where; Using join buffer ********************** 3. row ********************** id: 1 select_type: SIMPLE table: c type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 122 Extra: Using join buffer ********************** 4. row ********************** id: 1 select_type: SIMPLE table: o type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 326 Extra: Using where; Using join buffer ********************** 5. row ********************** id: 1 select_type: SIMPLE table: d type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 2996 Extra: Using where; Using join buffer 5 rows in set [0.00 sec]
2 - Toàn bộ bảng được duyệt để tìm dòng cho join. Đây là loại join tồi tệ nhất và thường cho thấy sự thiếu xót trong việc đánh chỉ mục.********************** 1. row ********************** id: 1 select_type: SIMPLE table: l type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 7 Extra: ********************** 2. row ********************** id: 1 select_type: SIMPLE table: p type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 110 Extra: Using where; Using join buffer ********************** 3. row ********************** id: 1 select_type: SIMPLE table: c type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 122 Extra: Using join buffer ********************** 4. row ********************** id: 1 select_type: SIMPLE table: o type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 326 Extra: Using where; Using join buffer ********************** 5. row ********************** id: 1 select_type: SIMPLE table: d type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 2996 Extra: Using where; Using join buffer 5 rows in set [0.00 sec]
3 - Hiển thị********************** 1. row ********************** id: 1 select_type: SIMPLE table: l type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 7 Extra: ********************** 2. row ********************** id: 1 select_type: SIMPLE table: p type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 110 Extra: Using where; Using join buffer ********************** 3. row ********************** id: 1 select_type: SIMPLE table: c type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 122 Extra: Using join buffer ********************** 4. row ********************** id: 1 select_type: SIMPLE table: o type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 326 Extra: Using where; Using join buffer ********************** 5. row ********************** id: 1 select_type: SIMPLE table: d type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 2996 Extra: Using where; Using join buffer 5 rows in set [0.00 sec]
4 có thể được dùng bởi MySQL để tìm dòng trong bảng, tuy nhiên nó có thể hoặc không thể được dùng. Trong thực tế, cột này đôi khi giúp cho việc tối ưu truy vấn, bởi nếu cột này trống [NULL], nó thường cho thấy không có chỉ mục liên quan được định nghĩa trong bảng.********************** 1. row ********************** id: 1 select_type: SIMPLE table: l type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 7 Extra: ********************** 2. row ********************** id: 1 select_type: SIMPLE table: p type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 110 Extra: Using where; Using join buffer ********************** 3. row ********************** id: 1 select_type: SIMPLE table: c type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 122 Extra: Using join buffer ********************** 4. row ********************** id: 1 select_type: SIMPLE table: o type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 326 Extra: Using where; Using join buffer ********************** 5. row ********************** id: 1 select_type: SIMPLE table: d type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 2996 Extra: Using where; Using join buffer 5 rows in set [0.00 sec]
key - Khóa thực sự được sử dụng bởi MySQL. Cột này có thể chứa khóa không được liệt kê ở cột
3. Trình tối ưu của MySQL luôn cố gắng tìm kiếm khóa tối ưu nhất cho truy vấn. Khi kết hợp nhiều bảng, nó có thể dùng khóa không nằm trong danh sách********************** 1. row ********************** id: 1 select_type: SIMPLE table: l type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 7 Extra: ********************** 2. row ********************** id: 1 select_type: SIMPLE table: p type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 110 Extra: Using where; Using join buffer ********************** 3. row ********************** id: 1 select_type: SIMPLE table: c type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 122 Extra: Using join buffer ********************** 4. row ********************** id: 1 select_type: SIMPLE table: o type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 326 Extra: Using where; Using join buffer ********************** 5. row ********************** id: 1 select_type: SIMPLE table: d type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 2996 Extra: Using where; Using join buffer 5 rows in set [0.00 sec]
3 nhưng lại đem về hiệu quả cao hơn.********************** 1. row ********************** id: 1 select_type: SIMPLE table: l type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 7 Extra: ********************** 2. row ********************** id: 1 select_type: SIMPLE table: p type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 110 Extra: Using where; Using join buffer ********************** 3. row ********************** id: 1 select_type: SIMPLE table: c type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 122 Extra: Using join buffer ********************** 4. row ********************** id: 1 select_type: SIMPLE table: o type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 326 Extra: Using where; Using join buffer ********************** 5. row ********************** id: 1 select_type: SIMPLE table: d type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 2996 Extra: Using where; Using join buffer 5 rows in set [0.00 sec]
7 - Chiều dài của khóa mà trình tối ưu truy vấn [Query Optimizer] sử dụng. Ví dụ,********************** 1. row ********************** id: 1 select_type: SIMPLE table: l type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 7 Extra: ********************** 2. row ********************** id: 1 select_type: SIMPLE table: p type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 110 Extra: Using where; Using join buffer ********************** 3. row ********************** id: 1 select_type: SIMPLE table: c type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 122 Extra: Using join buffer ********************** 4. row ********************** id: 1 select_type: SIMPLE table: o type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 326 Extra: Using where; Using join buffer ********************** 5. row ********************** id: 1 select_type: SIMPLE table: d type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 2996 Extra: Using where; Using join buffer 5 rows in set [0.00 sec]
7 mang giá trị 4 có nghĩa là nó cần bộ nhớ để lưu 4 ký tự. Bạn đọc có thể xem lại Yêu cầu về bộ nhớ cho từng kiểu dữ liệu trong MySQL.********************** 1. row ********************** id: 1 select_type: SIMPLE table: l type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 7 Extra: ********************** 2. row ********************** id: 1 select_type: SIMPLE table: p type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 110 Extra: Using where; Using join buffer ********************** 3. row ********************** id: 1 select_type: SIMPLE table: c type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 122 Extra: Using join buffer ********************** 4. row ********************** id: 1 select_type: SIMPLE table: o type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 326 Extra: Using where; Using join buffer ********************** 5. row ********************** id: 1 select_type: SIMPLE table: d type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 2996 Extra: Using where; Using join buffer 5 rows in set [0.00 sec]
1 - Tên cột hoặc hằng số được dùng để so sánh với chỉ mục được nêu ra ở cột********************** 1. row ********************** Level: Note Code: 1003 Message: select `World`.`City`.`Name` AS `Name` from `World`.`City` join `World`.`Country` where [[`World`.`City`.`CountryCode` = 'IND']] 1 row in set [0.00 sec]
9. MySQL có thể lấy ra một hằng số, hoặc một cột cho quá trình thực hiện truy vấn. Bạn có thể thấy trong ví dự sẽ được liệt kê dưới đây.********************** 1. row ********************** Level: Note Code: 1003 Message: select `World`.`City`.`Name` AS `Name` from `World`.`City` join `World`.`Country` where [[`World`.`City`.`CountryCode` = 'IND']] 1 row in set [0.00 sec]
1 - Số lượng bản ghi đã được duyệt để trả về kết quả. Đây cũng là một cột hết sức quan trọng cho việc tối ưu truy vấn, nhất là khi bạn dùngALTER TABLE customers ADD PRIMARY KEY [customerNumber]; ALTER TABLE employees ADD PRIMARY KEY [employeeNumber]; ALTER TABLE offices ADD PRIMARY KEY [officeCode]; ALTER TABLE orderdetails ADD PRIMARY KEY [orderNumber, productCode]; ALTER TABLE orders ADD PRIMARY KEY [orderNumber], ADD KEY [customerNumber]; ALTER TABLE payments ADD PRIMARY KEY [customerNumber, checkNumber]; ALTER TABLE productlines ADD PRIMARY KEY [productLine]; ALTER TABLE products ADD PRIMARY KEY [productCode], ADD KEY [buyPrice], ADD KEY [productLine]; ALTER TABLE productvariants ADD PRIMARY KEY [variantId], ADD KEY [buyPrice], ADD KEY [productCode];
0 hoặc truy vấn con.********************** 1. row ********************** id: 1 select_type: SIMPLE table: Country type: const possible_keys: PRIMARY key: PRIMARY key_len: 3 ref: const rows: 1 filtered: 100.00 Extra: ********************** 2. row ********************** id: 1 select_type: SIMPLE table: City type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 4079 filtered: 100.00 Extra: Using where 2 rows in set, 1 warning [0.00 sec]
3 - Các thông tin bổ sung liên quan đến quá trình thực hiện truy vấn. Các giá trị kiểu nhưALTER TABLE customers ADD PRIMARY KEY [customerNumber]; ALTER TABLE employees ADD PRIMARY KEY [employeeNumber]; ALTER TABLE offices ADD PRIMARY KEY [officeCode]; ALTER TABLE orderdetails ADD PRIMARY KEY [orderNumber, productCode]; ALTER TABLE orders ADD PRIMARY KEY [orderNumber], ADD KEY [customerNumber]; ALTER TABLE payments ADD PRIMARY KEY [customerNumber, checkNumber]; ALTER TABLE productlines ADD PRIMARY KEY [productLine]; ALTER TABLE products ADD PRIMARY KEY [productCode], ADD KEY [buyPrice], ADD KEY [productLine]; ALTER TABLE productvariants ADD PRIMARY KEY [variantId], ADD KEY [buyPrice], ADD KEY [productCode];
4 [dùng tạm thời],ALTER TABLE customers ADD PRIMARY KEY [customerNumber]; ALTER TABLE employees ADD PRIMARY KEY [employeeNumber]; ALTER TABLE offices ADD PRIMARY KEY [officeCode]; ALTER TABLE orderdetails ADD PRIMARY KEY [orderNumber, productCode]; ALTER TABLE orders ADD PRIMARY KEY [orderNumber], ADD KEY [customerNumber]; ALTER TABLE payments ADD PRIMARY KEY [customerNumber, checkNumber]; ALTER TABLE productlines ADD PRIMARY KEY [productLine]; ALTER TABLE products ADD PRIMARY KEY [productCode], ADD KEY [buyPrice], ADD KEY [productLine]; ALTER TABLE productvariants ADD PRIMARY KEY [variantId], ADD KEY [buyPrice], ADD KEY [productCode];
5 [dùng sắp xếp file],... của cột này có thể cho thấy một truy vấn không thực sự tốt. Danh sách đầy đủ của các giá trị có thể có ở cột này có thể xem tại Tài liệu MySQLALTER TABLE customers ADD PRIMARY KEY [customerNumber]; ALTER TABLE employees ADD PRIMARY KEY [employeeNumber]; ALTER TABLE offices ADD PRIMARY KEY [officeCode]; ALTER TABLE orderdetails ADD PRIMARY KEY [orderNumber, productCode]; ALTER TABLE orders ADD PRIMARY KEY [orderNumber], ADD KEY [customerNumber]; ALTER TABLE payments ADD PRIMARY KEY [customerNumber, checkNumber]; ALTER TABLE productlines ADD PRIMARY KEY [productLine]; ALTER TABLE products ADD PRIMARY KEY [productCode], ADD KEY [buyPrice], ADD KEY [productLine]; ALTER TABLE productvariants ADD PRIMARY KEY [variantId], ADD KEY [buyPrice], ADD KEY [productCode];
Bạn có thể bổ sung thêm từ khóa
ALTER TABLE customers
ADD PRIMARY KEY [customerNumber];
ALTER TABLE employees
ADD PRIMARY KEY [employeeNumber];
ALTER TABLE offices
ADD PRIMARY KEY [officeCode];
ALTER TABLE orderdetails
ADD PRIMARY KEY [orderNumber, productCode];
ALTER TABLE orders
ADD PRIMARY KEY [orderNumber],
ADD KEY [customerNumber];
ALTER TABLE payments
ADD PRIMARY KEY [customerNumber, checkNumber];
ALTER TABLE productlines
ADD PRIMARY KEY [productLine];
ALTER TABLE products
ADD PRIMARY KEY [productCode],
ADD KEY [buyPrice],
ADD KEY [productLine];
ALTER TABLE productvariants
ADD PRIMARY KEY [variantId],
ADD KEY [buyPrice],
ADD KEY [productCode];
6 sau ********************** 1. row **********************
id: 1
select_type: SIMPLE
table: categories
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
Extra:
1 row in set [0.00 sec]
5 và MySQL sẽ đưa ra các thông tin bổ sung về quá trình thực hiện truy vấn. Để xem chi tiết, thực hiện lệnh ALTER TABLE customers
ADD PRIMARY KEY [customerNumber];
ALTER TABLE employees
ADD PRIMARY KEY [employeeNumber];
ALTER TABLE offices
ADD PRIMARY KEY [officeCode];
ALTER TABLE orderdetails
ADD PRIMARY KEY [orderNumber, productCode];
ALTER TABLE orders
ADD PRIMARY KEY [orderNumber],
ADD KEY [customerNumber];
ALTER TABLE payments
ADD PRIMARY KEY [customerNumber, checkNumber];
ALTER TABLE productlines
ADD PRIMARY KEY [productLine];
ALTER TABLE products
ADD PRIMARY KEY [productCode],
ADD KEY [buyPrice],
ADD KEY [productLine];
ALTER TABLE productvariants
ADD PRIMARY KEY [variantId],
ADD KEY [buyPrice],
ADD KEY [productCode];
8 ngay sau lệnh ********************** 1. row **********************
id: 1
select_type: SIMPLE
table: categories
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
Extra:
1 row in set [0.00 sec]
5. Nó thường được dùng để xem các câu truy vấn được thực hiện sau bất cứ thay đổi nào được tạo ra bởi Query Optimizer.EXPLAIN EXTENDED SELECT City.Name FROM City
JOIN Country ON [City.CountryCode = Country.Code]
WHERE City.CountryCode = 'IND' AND Country.Continent = 'Asia'\G
********************** 1. row **********************
id: 1
select_type: SIMPLE
table: Country
type: const
possible_keys: PRIMARY
key: PRIMARY
key_len: 3
ref: const
rows: 1
filtered: 100.00
Extra:
********************** 2. row **********************
id: 1
select_type: SIMPLE
table: City
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4079
filtered: 100.00
Extra: Using where
2 rows in set, 1 warning [0.00 sec]
SHOW WARNINGS\G
********************** 1. row **********************
Level: Note
Code: 1003
Message: select `World`.`City`.`Name` AS `Name` from `World`.`City` join `World`.`Country` where [[`World`.`City`.`CountryCode` = 'IND']]
1 row in set [0.00 sec]
Khắc phục sự cố về hiệu năng với EXPLAIN
Giờ hãy cùng tìm hiểu làm cách nào chúng ta có thể tối ưu một truy vấn hiệu năng thấp bằng cách phân tích kết quả của
********************** 1. row **********************
id: 1
select_type: SIMPLE
table: categories
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
Extra:
1 row in set [0.00 sec]
5. Trong thực tế, không có gì phải nghi ngờ khi chúng ta sẽ có rất nhiều bảng với rất nhiều quan hệ với nhau, tuy nhiên đôi khi thật khó để biết được cách tốt nhất để viết một truy vấn.Ở đây, tôi đã tạo ra một cơ sở dữ liệu mẫu cho một ứng dụng thương mại mà ở đó không có chỉ mục, khóa chính và sẽ mô tả ảnh hưởng của thiết kế tồi tệ này bằng cách viết ra các truy vấn phức tạp. Bạn có thể download Mô hình DB từ Github.
Từ người dịch: Để bạn đọc có thể hiểu được mô hình DB dùng trong bài viết này, tôi đã vẽ lại theo mô hình của tác giả và đính kèm ảnh phía dưới. Rất mong có thể giúp ích cho phần tìm hiểu query sau đây.
EXPLAIN SELECT * FROM
orderdetails d
INNER JOIN orders o ON d.orderNumber = o.orderNumber
INNER JOIN products p ON p.productCode = d.productCode
INNER JOIN productlines l ON p.productLine = l.productLine
INNER JOIN customers c on c.customerNumber = o.customerNumber
WHERE o.orderNumber = 10101\G
********************** 1. row **********************
id: 1
select_type: SIMPLE
table: l
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 7
Extra:
********************** 2. row **********************
id: 1
select_type: SIMPLE
table: p
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 110
Extra: Using where; Using join buffer
********************** 3. row **********************
id: 1
select_type: SIMPLE
table: c
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 122
Extra: Using join buffer
********************** 4. row **********************
id: 1
select_type: SIMPLE
table: o
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 326
Extra: Using where; Using join buffer
********************** 5. row **********************
id: 1
select_type: SIMPLE
table: d
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 2996
Extra: Using where; Using join buffer
5 rows in set [0.00 sec]
Nhìn vào kết quả trên, bạn thấy được tất cả biểu hiện của một truy vấn tồi tệ. Tuy nhiên, kể cả khi tôi có viết truy vấn tốt hơn, thì kết quả vẫn tương tự, bởi không có chỉ mục. Loại join là
********************** 1. row **********************
id: 1
select_type: SIMPLE
table: o
type: const
possible_keys: PRIMARY,customerNumber
key: PRIMARY
key_len: 4
ref: const
rows: 1
Extra:
********************** 2. row **********************
id: 1
select_type: SIMPLE
table: c
type: const
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: const
rows: 1
Extra:
********************** 3. row **********************
id: 1
select_type: SIMPLE
table: d
type: ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: const
rows: 4
Extra:
********************** 4. row **********************
id: 1
select_type: SIMPLE
table: p
type: eq_ref
possible_keys: PRIMARY,productLine
key: PRIMARY
key_len: 17
ref: classicmodels.d.productCode
rows: 1
Extra:
********************** 5. row **********************
id: 1
select_type: SIMPLE
table: l
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 52
ref: classicmodels.p.productLine
rows: 1
Extra:
5 rows in set [0.00 sec]
1 [loại tồi nhất], có nghĩa rằng MySQL không thể xác định bất cứ khóa nào để dùng cho join, và do vậy cả ********************** 1. row **********************
id: 1
select_type: SIMPLE
table: l
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 7
Extra:
********************** 2. row **********************
id: 1
select_type: SIMPLE
table: p
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 110
Extra: Using where; Using join buffer
********************** 3. row **********************
id: 1
select_type: SIMPLE
table: c
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 122
Extra: Using join buffer
********************** 4. row **********************
id: 1
select_type: SIMPLE
table: o
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 326
Extra: Using where; Using join buffer
********************** 5. row **********************
id: 1
select_type: SIMPLE
table: d
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 2996
Extra: Using where; Using join buffer
5 rows in set [0.00 sec]
3 và ********************** 1. row **********************
Level: Note
Code: 1003
Message: select `World`.`City`.`Name` AS `Name` from `World`.`City` join `World`.`Country` where [[`World`.`City`.`CountryCode` = 'IND']]
1 row in set [0.00 sec]
9 đều trống. Quan trọng hơn, trường ALTER TABLE customers
ADD PRIMARY KEY [customerNumber];
ALTER TABLE employees
ADD PRIMARY KEY [employeeNumber];
ALTER TABLE offices
ADD PRIMARY KEY [officeCode];
ALTER TABLE orderdetails
ADD PRIMARY KEY [orderNumber, productCode];
ALTER TABLE orders
ADD PRIMARY KEY [orderNumber],
ADD KEY [customerNumber];
ALTER TABLE payments
ADD PRIMARY KEY [customerNumber, checkNumber];
ALTER TABLE productlines
ADD PRIMARY KEY [productLine];
ALTER TABLE products
ADD PRIMARY KEY [productCode],
ADD KEY [buyPrice],
ADD KEY [productLine];
ALTER TABLE productvariants
ADD PRIMARY KEY [variantId],
ADD KEY [buyPrice],
ADD KEY [productCode];
1 cho thấy MySQL phải duyệt tất cả các bản ghi của từng bảng cho câu truy vấn này. Có nghĩa, để chạy câu truy vấn, nó cần duyệt ********************** 1. row **********************
id: 1
select_type: SIMPLE
table: o
type: const
possible_keys: PRIMARY,customerNumber
key: PRIMARY
key_len: 4
ref: const
rows: 1
Extra:
********************** 2. row **********************
id: 1
select_type: SIMPLE
table: c
type: const
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: const
rows: 1
Extra:
********************** 3. row **********************
id: 1
select_type: SIMPLE
table: d
type: ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: const
rows: 4
Extra:
********************** 4. row **********************
id: 1
select_type: SIMPLE
table: p
type: eq_ref
possible_keys: PRIMARY,productLine
key: PRIMARY
key_len: 17
ref: classicmodels.d.productCode
rows: 1
Extra:
********************** 5. row **********************
id: 1
select_type: SIMPLE
table: l
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 52
ref: classicmodels.p.productLine
rows: 1
Extra:
5 rows in set [0.00 sec]
5 bản ghi để tìm ra kết quả. Điều này thật khủng khiếp và nó sẽ còn tăng thêm khi cơ sở dữ liệu lớn hơn.Bây giờ, chúng ta thử thêm 1 số chỉ mục khá hiển nhiên, như khóa chính cho từng bảng, và thực hiện truy vấn một lần nữa. Theo thông lệ cơ bản, bạn tìm đến các cột dùng để JOIN và cho chúng làm khóa, bởi MySQL sẽ luôn tìm theo các cột đó để tra cứu các bản ghi.
ALTER TABLE customers
ADD PRIMARY KEY [customerNumber];
ALTER TABLE employees
ADD PRIMARY KEY [employeeNumber];
ALTER TABLE offices
ADD PRIMARY KEY [officeCode];
ALTER TABLE orderdetails
ADD PRIMARY KEY [orderNumber, productCode];
ALTER TABLE orders
ADD PRIMARY KEY [orderNumber],
ADD KEY [customerNumber];
ALTER TABLE payments
ADD PRIMARY KEY [customerNumber, checkNumber];
ALTER TABLE productlines
ADD PRIMARY KEY [productLine];
ALTER TABLE products
ADD PRIMARY KEY [productCode],
ADD KEY [buyPrice],
ADD KEY [productLine];
ALTER TABLE productvariants
ADD PRIMARY KEY [variantId],
ADD KEY [buyPrice],
ADD KEY [productCode];
Giờ chúng ta chạy lại truy vấn sau khi đã thêm chỉ mục.
********************** 1. row **********************
id: 1
select_type: SIMPLE
table: o
type: const
possible_keys: PRIMARY,customerNumber
key: PRIMARY
key_len: 4
ref: const
rows: 1
Extra:
********************** 2. row **********************
id: 1
select_type: SIMPLE
table: c
type: const
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: const
rows: 1
Extra:
********************** 3. row **********************
id: 1
select_type: SIMPLE
table: d
type: ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: const
rows: 4
Extra:
********************** 4. row **********************
id: 1
select_type: SIMPLE
table: p
type: eq_ref
possible_keys: PRIMARY,productLine
key: PRIMARY
key_len: 17
ref: classicmodels.d.productCode
rows: 1
Extra:
********************** 5. row **********************
id: 1
select_type: SIMPLE
table: l
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 52
ref: classicmodels.p.productLine
rows: 1
Extra:
5 rows in set [0.00 sec]
Sau khi thêm chỉ mục, số lượng bản ghi cần duyệt giảm xuống còn
********************** 1. row **********************
id: 1
select_type: SIMPLE
table: o
type: const
possible_keys: PRIMARY,customerNumber
key: PRIMARY
key_len: 4
ref: const
rows: 1
Extra:
********************** 2. row **********************
id: 1
select_type: SIMPLE
table: c
type: const
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: const
rows: 1
Extra:
********************** 3. row **********************
id: 1
select_type: SIMPLE
table: d
type: ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: const
rows: 4
Extra:
********************** 4. row **********************
id: 1
select_type: SIMPLE
table: p
type: eq_ref
possible_keys: PRIMARY,productLine
key: PRIMARY
key_len: 17
ref: classicmodels.d.productCode
rows: 1
Extra:
********************** 5. row **********************
id: 1
select_type: SIMPLE
table: l
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 52
ref: classicmodels.p.productLine
rows: 1
Extra:
5 rows in set [0.00 sec]
6. Điều đó có nghĩa là, với mỗi bản ghi có ********************** 1. row **********************
id: 1
select_type: SIMPLE
table: o
type: const
possible_keys: PRIMARY,customerNumber
key: PRIMARY
key_len: 4
ref: const
rows: 1
Extra:
********************** 2. row **********************
id: 1
select_type: SIMPLE
table: c
type: const
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: const
rows: 1
Extra:
********************** 3. row **********************
id: 1
select_type: SIMPLE
table: d
type: ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: const
rows: 4
Extra:
********************** 4. row **********************
id: 1
select_type: SIMPLE
table: p
type: eq_ref
possible_keys: PRIMARY,productLine
key: PRIMARY
key_len: 17
ref: classicmodels.d.productCode
rows: 1
Extra:
********************** 5. row **********************
id: 1
select_type: SIMPLE
table: l
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 52
ref: classicmodels.p.productLine
rows: 1
Extra:
5 rows in set [0.00 sec]
7 là 10101 trong bảng ********************** 1. row **********************
id: 1
select_type: SIMPLE
table: o
type: const
possible_keys: PRIMARY,customerNumber
key: PRIMARY
key_len: 4
ref: const
rows: 1
Extra:
********************** 2. row **********************
id: 1
select_type: SIMPLE
table: c
type: const
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: const
rows: 1
Extra:
********************** 3. row **********************
id: 1
select_type: SIMPLE
table: d
type: ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: const
rows: 4
Extra:
********************** 4. row **********************
id: 1
select_type: SIMPLE
table: p
type: eq_ref
possible_keys: PRIMARY,productLine
key: PRIMARY
key_len: 17
ref: classicmodels.d.productCode
rows: 1
Extra:
********************** 5. row **********************
id: 1
select_type: SIMPLE
table: l
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 52
ref: classicmodels.p.productLine
rows: 1
Extra:
5 rows in set [0.00 sec]
8, MySQL có thể tìm trự tiếp bản ghi thỏa mãn trong tất cả các bản ghi khác bằng cách sử dụng chỉ mục và không cần phải duyệt lại cả bảng.Ở dòng đầu tiên, loại join là
SHOW WARNINGS\G
6, loại nhanh nhất với bảng có nhiều hơn 1 bản ghi. MySQL có thể sử dụng khóa chính trong trường hợp này. Trường ********************** 1. row **********************
Level: Note
Code: 1003
Message: select `World`.`City`.`Name` AS `Name` from `World`.`City` join `World`.`Country` where [[`World`.`City`.`CountryCode` = 'IND']]
1 row in set [0.00 sec]
1 trả về kết quả SHOW WARNINGS\G
6, có nghĩa là không gì ngoài giá trị 10101 được dùng trong lệnh ********************** 1. row **********************
id: 1
select_type: SIMPLE
table: categories
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
Extra:
1 row in set [0.00 sec]
02.Tiếp theo hãy xem một truy vấn khác. Ở đây, chúng ta chỉ đơn giản hợp 2 bảng lại,
********************** 1. row **********************
id: 1
select_type: SIMPLE
table: categories
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
Extra:
1 row in set [0.00 sec]
03 và ********************** 1. row **********************
id: 1
select_type: SIMPLE
table: categories
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
Extra:
1 row in set [0.00 sec]
04, cả hai đều được join với ********************** 1. row **********************
id: 1
select_type: SIMPLE
table: categories
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
Extra:
1 row in set [0.00 sec]
05. Bảng ********************** 1. row **********************
id: 1
select_type: SIMPLE
table: categories
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
Extra:
1 row in set [0.00 sec]
04 gồm các biến thể của ********************** 1. row **********************
id: 1
select_type: SIMPLE
table: categories
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
Extra:
1 row in set [0.00 sec]
07 ở dạng khóa ngoài.********************** 1. row **********************
id: 1
select_type: SIMPLE
table: categories
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
Extra:
1 row in set [0.00 sec]
0********************** 1. row **********************
id: 1
select_type: SIMPLE
table: categories
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
Extra:
1 row in set [0.00 sec]
1Bạn có thể thấy rất nhiều vấn đề ở câu truy vấn này. Nó duyệt tất cả bản ghi ở bảng
********************** 1. row **********************
id: 1
select_type: SIMPLE
table: categories
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
Extra:
1 row in set [0.00 sec]
03 và ********************** 1. row **********************
id: 1
select_type: SIMPLE
table: categories
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
Extra:
1 row in set [0.00 sec]
04. Vì không có chỉ mục nào ở các bảng này cho trường ********************** 1. row **********************
id: 1
select_type: SIMPLE
table: categories
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
Extra:
1 row in set [0.00 sec]
10 và ********************** 1. row **********************
id: 1
select_type: SIMPLE
table: categories
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
Extra:
1 row in set [0.00 sec]
11, kết quả trả về cột ********************** 1. row **********************
id: 1
select_type: SIMPLE
table: l
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 7
Extra:
********************** 2. row **********************
id: 1
select_type: SIMPLE
table: p
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 110
Extra: Using where; Using join buffer
********************** 3. row **********************
id: 1
select_type: SIMPLE
table: c
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 122
Extra: Using join buffer
********************** 4. row **********************
id: 1
select_type: SIMPLE
table: o
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 326
Extra: Using where; Using join buffer
********************** 5. row **********************
id: 1
select_type: SIMPLE
table: d
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 2996
Extra: Using where; Using join buffer
5 rows in set [0.00 sec]
3 và ********************** 1. row **********************
Level: Note
Code: 1003
Message: select `World`.`City`.`Name` AS `Name` from `World`.`City` join `World`.`Country` where [[`World`.`City`.`CountryCode` = 'IND']]
1 row in set [0.00 sec]
9 đều là trống. Trạng thái của ********************** 1. row **********************
id: 1
select_type: SIMPLE
table: categories
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
Extra:
1 row in set [0.00 sec]
03 và ********************** 1. row **********************
id: 1
select_type: SIMPLE
table: categories
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
Extra:
1 row in set [0.00 sec]
15 được kiểm tra sau khi hợp lại EXPLAIN EXTENDED SELECT City.Name FROM City
JOIN Country ON [City.CountryCode = Country.Code]
WHERE City.CountryCode = 'IND' AND Country.Continent = 'Asia'\G
7, do vậy việc cho chúng vào trong EXPLAIN EXTENDED SELECT City.Name FROM City
JOIN Country ON [City.CountryCode = Country.Code]
WHERE City.CountryCode = 'IND' AND Country.Continent = 'Asia'\G
7 sẽ giảm số lượng bản ghi. Giờ chúng ta thử thêm vài chỉ mục và viết lại truy vấn.********************** 1. row **********************
id: 1
select_type: SIMPLE
table: categories
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
Extra:
1 row in set [0.00 sec]
2********************** 1. row **********************
id: 1
select_type: SIMPLE
table: categories
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
Extra:
1 row in set [0.00 sec]
3********************** 1. row **********************
id: 1
select_type: SIMPLE
table: categories
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
Extra:
1 row in set [0.00 sec]
4Như bạn thấy ở kết quả, số lượng dòng được duyệt đả giảm đáng kể, từ
********************** 1. row **********************
id: 1
select_type: SIMPLE
table: categories
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
Extra:
1 row in set [0.00 sec]
18 xuống còn ********************** 1. row **********************
id: 1
select_type: SIMPLE
table: categories
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
Extra:
1 row in set [0.00 sec]
19, thực sự là một hiệu quả rất đáng ghi nhận. Nếu bạn cố gắng chạy cùng truy vấn, mà không sắp xếp lại từ trước, ngay sau khi thêm chỉ mục, bạn sẽ không thể thấy được số lượng giảm đáng kể như vậy. MySQL không thể sử dụng chỉ mục bởi nó dùng ********************** 1. row **********************
id: 1
select_type: SIMPLE
table: categories
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
Extra:
1 row in set [0.00 sec]
02 trong kết quả trả về. Sau khi di chuyển điều kiện vào bên trong EXPLAIN EXTENDED SELECT City.Name FROM City
JOIN Country ON [City.CountryCode = Country.Code]
WHERE City.CountryCode = 'IND' AND Country.Continent = 'Asia'\G
7, MySQL đã có thể dùng chỉ mục. Điều đó có nghĩa là thêm chỉ mục không phải là đủ, MySWL sẽ không thể dùng được chỉ mục đó trừ khi bạn viết câu truy vấn thích hợp.Kết luận
Trong bài viết này, tôi đã thỏa luận về từ khóa
********************** 1. row **********************
id: 1
select_type: SIMPLE
table: categories
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
Extra:
1 row in set [0.00 sec]
5 của MySQL, ý nghĩa của kết quả trả về và cách dùng nó để viết truy vấn tốt hơn. Trong thực tế, nó còn có thể hữu dụng hơn ví dụ được đưa ra ở đây. Thực tế, bạn sẽ thường xuyên join nhiều bảng với câu lệnh ********************** 1. row **********************
id: 1
select_type: SIMPLE
table: categories
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
Extra:
1 row in set [0.00 sec]
02 phức tạp. Việc chỉ đơn giản thêm chỉ mục sẽ không phải lúc nào cũng giúp bạn, bạn cần dành thời gian suy nghĩ kỹ càng hơn và viết truy vấn tốt hơn.Quan điểm cá nhân
Lần đầu tiên tôi biết đến
********************** 1. row **********************
id: 1
select_type: SIMPLE
table: categories
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
Extra:
1 row in set [0.00 sec]
5 cũng là khi tôi biết được chương trình của mình thực hiện quá nhiều truy vấn sử dụng ********************** 1. row **********************
id: 1
select_type: SIMPLE
table: categories
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
Extra:
1 row in set [0.00 sec]
25 [Phần ALTER TABLE customers
ADD PRIMARY KEY [customerNumber];
ALTER TABLE employees
ADD PRIMARY KEY [employeeNumber];
ALTER TABLE offices
ADD PRIMARY KEY [officeCode];
ALTER TABLE orderdetails
ADD PRIMARY KEY [orderNumber, productCode];
ALTER TABLE orders
ADD PRIMARY KEY [orderNumber],
ADD KEY [customerNumber];
ALTER TABLE payments
ADD PRIMARY KEY [customerNumber, checkNumber];
ALTER TABLE productlines
ADD PRIMARY KEY [productLine];
ALTER TABLE products
ADD PRIMARY KEY [productCode],
ADD KEY [buyPrice],
ADD KEY [productLine];
ALTER TABLE productvariants
ADD PRIMARY KEY [variantId],
ADD KEY [buyPrice],
ADD KEY [productCode];
3 trả về ALTER TABLE customers
ADD PRIMARY KEY [customerNumber];
ALTER TABLE employees
ADD PRIMARY KEY [employeeNumber];
ALTER TABLE offices
ADD PRIMARY KEY [officeCode];
ALTER TABLE orderdetails
ADD PRIMARY KEY [orderNumber, productCode];
ALTER TABLE orders
ADD PRIMARY KEY [orderNumber],
ADD KEY [customerNumber];
ALTER TABLE payments
ADD PRIMARY KEY [customerNumber, checkNumber];
ALTER TABLE productlines
ADD PRIMARY KEY [productLine];
ALTER TABLE products
ADD PRIMARY KEY [productCode],
ADD KEY [buyPrice],
ADD KEY [productLine];
ALTER TABLE productvariants
ADD PRIMARY KEY [variantId],
ADD KEY [buyPrice],
ADD KEY [productCode];
5]. Đây là 1 sắp xếp không có index và rất nguy hiểm khi làm việc với lượng dữ liệu lớn. Việc dùng ********************** 1. row **********************
id: 1
select_type: SIMPLE
table: categories
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
Extra:
1 row in set [0.00 sec]
5 giúp tôi phát hiện ra thiếu xót trong thiết kế DB của mình ở thời điểm đó và qua đó biết cách chỉnh sửa thiết kế của mình.Ngày nay, việc sử dụng các framework hỗ trợ ORM khiến cho các lập trình viên không quan tâm đến quá trình truy vấn dữ liệu trong DB, kéo theo đó là các vấn đề về hiệu năng khi ứng dụng to lên. Ngược lại, việc viết truy vấn bằng tay, dù tốn thời gian nhưng lại đem lại hiệu quả cao về hiệu năng sau này cũng như nâng cao hiểu biết của lập trình viên. Khi tôi còn là thực tập sinh, tôi phải viết tất cả truy vấn bằng tay và theo chỉ định của người hướng dẫn, tôi phải tự
********************** 1. row **********************
id: 1
select_type: SIMPLE
table: categories
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
Extra:
1 row in set [0.00 sec]
5 tất cả query trước khi code. Những trải nghiệm đó đã giúp tôi tích lũy được rất nhiều kinh nghiệm cho công việc sau này. Rất mong mọi người cũng có cùng quan điểm và dành thời gian ********************** 1. row **********************
id: 1
select_type: SIMPLE
table: categories
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
Extra:
1 row in set [0.00 sec]
5 câu query của mình trước khi bắt tay vào code ứng dụng thực tế.