Tôi có một bảng Joomla với hàng ngàn hàng nội dung (khoảng 3 triệu). Tôi đang gặp một chút rắc rối khi viết lại các truy vấn cơ sở dữ liệu càng nhanh càng tốt khi truy vấn các bảng.Truy vấn MySQL phức tạp vẫn sử dụng filesort mặc dù chỉ mục tồn tại
Đây là truy vấn đầy đủ của tôi:
SELECT cc.title AS category, a.id, a.title, a.alias, a.title_alias, a.introtext, a.fulltext, a.sectionid, a.state, a.catid, a.created, a.created_by, a.created_by_alias, a.modified, a.modified_by, a.checked_out, a.checked_out_time, a.publish_up, a.publish_down, a.attribs, a.hits, a.images, a.urls, a.ordering, a.metakey, a.metadesc, a.access, CASE WHEN CHAR_LENGTH(a.alias) THEN CONCAT_WS(":", a.id, a.alias) ELSE a.id END AS slug, CASE WHEN CHAR_LENGTH(cc.alias) THEN CONCAT_WS(":", cc.id, cc.alias) ELSE cc.id END AS catslug, CHAR_LENGTH(a.`fulltext`) AS readmore, u.name AS author, u.usertype, g.name AS groups, u.email AS author_email
FROM j15_content AS a
LEFT JOIN j15_categories AS cc
ON a.catid = cc.id
LEFT JOIN j15_users AS u
ON u.id = a.created_by
LEFT JOIN j15_groups AS g
ON a.access = g.id
WHERE 1
AND a.access <= 0
AND a.catid = 108
AND a.state = 1
AND (publish_up = '0000-00-00 00:00:00' OR publish_up <= '2012-02-08 00:16:26')
AND (publish_down = '0000-00-00 00:00:00' OR publish_down >= '2012-02-08 00:16:26')
ORDER BY a.title, a.created DESC
LIMIT 0, 10
Đây là kết quả từ một giải thích:
+----+-------------+-------+--------+-------------------------------------------------------+-----------+---------+---------------------------+---------+-----------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+-------------------------------------------------------+-----------+---------+---------------------------+---------+-----------------------------+
| 1 | SIMPLE | a | ref | idx_access,idx_state,idx_catid,idx_access_state_catid | idx_catid | 4 | const | 3108187 | Using where; Using filesort |
| 1 | SIMPLE | cc | const | PRIMARY | PRIMARY | 4 | const | 1 | |
| 1 | SIMPLE | u | eq_ref | PRIMARY | PRIMARY | 4 | database.a.created_by | 1 | |
| 1 | SIMPLE | g | eq_ref | PRIMARY | PRIMARY | 1 | database.a.access | 1 | |
+----+-------------+-------+--------+-------------------------------------------------------+-----------+---------+---------------------------+---------+-----------------------------+
Và để hiển thị những gì chỉ số tồn tại, SHOW INDEX TỪ j15_content:
+-------------+------------+------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-------------+------------+------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| j15_content | 0 | PRIMARY | 1 | id | A | 3228356 | NULL | NULL | | BTREE | |
| j15_content | 1 | idx_section | 1 | sectionid | A | 2 | NULL | NULL | | BTREE | |
| j15_content | 1 | idx_access | 1 | access | A | 1 | NULL | NULL | | BTREE | |
| j15_content | 1 | idx_checkout | 1 | checked_out | A | 2 | NULL | NULL | | BTREE | |
| j15_content | 1 | idx_state | 1 | state | A | 2 | NULL | NULL | | BTREE | |
| j15_content | 1 | idx_catid | 1 | catid | A | 6 | NULL | NULL | | BTREE | |
| j15_content | 1 | idx_createdby | 1 | created_by | A | 1 | NULL | NULL | | BTREE | |
| j15_content | 1 | title | 1 | title | A | 201772 | 4 | NULL | | BTREE | |
| j15_content | 1 | idx_access_state_catid | 1 | access | A | 1 | NULL | NULL | | BTREE | |
| j15_content | 1 | idx_access_state_catid | 2 | state | A | 2 | NULL | NULL | | BTREE | |
| j15_content | 1 | idx_access_state_catid | 3 | catid | A | 7 | NULL | NULL | | BTREE | |
| j15_content | 1 | idx_title_created | 1 | title | A | 3228356 | 8 | NULL | | BTREE | |
| j15_content | 1 | idx_title_created | 2 | created | A | 3228356 | NULL | NULL | | BTREE | |
+-------------+------------+------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
Như bạn có thể thấy có một vài mẩu dữ liệu được lấy từ cơ sở dữ liệu. Bây giờ tôi đã thử nghiệm bằng cách đơn giản hóa truy vấn mà vấn đề thực sự nằm trong mệnh đề ORDER BY. Nếu không có lệnh áp dụng các kết quả, truy vấn là khá nhạy, đây là một lời giải thích:
+----+-------------+-------+--------+-------------------------------------------------------+-----------+---------+---------------------------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+-------------------------------------------------------+-----------+---------+---------------------------+---------+-------------+
| 1 | SIMPLE | a | ref | idx_access,idx_state,idx_catid,idx_access_state_catid | idx_catid | 4 | const | 3108187 | Using where |
| 1 | SIMPLE | cc | const | PRIMARY | PRIMARY | 4 | const | 1 | |
| 1 | SIMPLE | u | eq_ref | PRIMARY | PRIMARY | 4 | database.a.created_by | 1 | |
| 1 | SIMPLE | g | eq_ref | PRIMARY | PRIMARY | 1 | database.a.access | 1 | |
+----+-------------+-------+--------+-------------------------------------------------------+-----------+---------+---------------------------+---------+-------------+
Như bạn thấy đó là filesort chết người đó là giết chết các máy chủ. Với nhiều hàng này, tôi đang cố gắng hết sức để tối ưu hóa mọi thứ thông qua các chỉ mục nhưng vẫn có điều gì đó không đúng với điều này. Bất kỳ đầu vào sẽ được đánh giá rất nhiều.
Cố gắng sử dụng FORCE INDEX vô ích:
explain SELECT cc.title AS category, a.id, a.title, a.alias, a.title_alias, a.introtext, a.fulltext, a.sectionid, a.state, a.catid, a.created, a.created_by, a.created_by_alias, a.modified, a.modified_by, a.checked_out, a.checked_out_time, a.publish_up, a.publish_down, a.attribs, a.hits, a.images, a.urls, a.ordering, a.metakey, a.metadesc, a.access, CASE WHEN CHAR_LENGTH(a.alias) THEN CONCAT_WS(":", a.id, a.alias) ELSE a.id END AS slug, CASE WHEN CHAR_LENGTH(cc.alias) THEN CONCAT_WS(":", cc.id, cc.alias) ELSE cc.id END AS catslug, CHAR_LENGTH(a.`fulltext`) AS readmore, u.name AS author, u.usertype, g.name AS groups, u.email AS author_email
-> FROM bak_content AS a
-> FORCE INDEX (idx_title_created)
-> LEFT JOIN bak_categories AS cc
-> ON a.catid = cc.id
-> LEFT JOIN bak_users AS u
-> ON u.id = a.created_by
-> LEFT JOIN bak_groups AS g
-> ON a.access = g.id
-> WHERE 1
-> AND a.access <= 0
-> AND a.catid = 108
-> AND a.state = 1
-> AND (publish_up = '0000-00-00 00:00:00' OR publish_up <= '2012-02-08
-> AND (publish_down = '0000-00-00 00:00:00' OR publish_down >= '2012-0
-> ORDER BY a.title, a.created DESC
-> LIMIT 0, 10;
Tạo:
+----+-------------+-------+--------+---------------+---------+---------+-------
| id | select_type | table | type | possible_keys | key | key_len | ref
+----+-------------+-------+--------+---------------+---------+---------+-------
| 1 | SIMPLE | a | ALL | NULL | NULL | NULL | NULL
| 1 | SIMPLE | cc | const | PRIMARY | PRIMARY | 4 | const
| 1 | SIMPLE | u | eq_ref | PRIMARY | PRIMARY | 4 | database
| 1 | SIMPLE | g | eq_ref | PRIMARY | PRIMARY | 1 | database
+----+-------------+-------+--------+---------------+---------+---------+-------
Tôi sẽ thử một trong các chỉ mục này: '(trạng thái, catid, truy cập)' hoặc '(trạng thái, catid, publish_up)' hoặc '(trạng thái, catid, publish_down)' –
Nếu bạn không sử dụng 'LIMIT' nhiều hàng được trả về? –
Bạn cũng có thể thử sử dụng chỉ mục 'idx_title_created'. –