[英]MySQL JOIN take more than 10 seconds
簡而言之,有兩個表, activities_log
有330萬行,而posts
有20K行。 當一些查詢加入他們的過程超過15秒! (╥﹏╥)
我做錯了什么? 我可以做些什么來優化?
它正在此服務器上運行:
# QUERY:
select `posts`.`page_id` from `activities_log` left join `posts` on `posts`.`id` = `activities_log`.`post_id`;
3345753 rows in set (17.40 sec)
# EXPLAIN:
+----+-------------+----------------+------------+--------+---------------+------------------------------+---------+------------------------------------+---------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+----------------+------------+--------+---------------+------------------------------+---------+------------------------------------+---------+----------+-------------+
| 1 | SIMPLE | activities_log | NULL | index | NULL | activities_log_post_id_index | 145 | NULL | 3203032 | 100.00 | Using index |
| 1 | SIMPLE | posts | NULL | eq_ref | PRIMARY | PRIMARY | 144 | prod_api_v1.activities_log.post_id | 1 | 100.00 | NULL |
+----+-------------+----------------+------------+--------+---------------+------------------------------+---------+------------------------------------+---------+----------+-------------+
2 rows in set, 1 warning (0.01 sec)
select count(*) from `activities_log`;
+----------+
| count(*) |
+----------+
| 3345770 |
+----------+
1 row in set (1.04 sec)
show index from activities_log;
+----------------+------------+------------------------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+----------------+------------+------------------------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| activities_log | 0 | PRIMARY | 1 | id | A | 2984883 | NULL | NULL | | BTREE | | |
| activities_log | 1 | activities_log_page_id_index | 1 | page_id | A | 343 | NULL | NULL | YES | BTREE | | |
| activities_log | 1 | activities_log_activity_id_index | 1 | activity_id | A | 15 | NULL | NULL | | BTREE | | |
| activities_log | 1 | activities_log_post_id_index | 1 | post_id | A | 43894 | NULL | NULL | YES | BTREE | | |
| activities_log | 1 | activities_log_session_token_index | 1 | session_token | A | 4431 | NULL | NULL | YES | BTREE | | |
| activities_log | 1 | activities_log_user_id_index | 1 | user_id | A | 17908 | NULL | NULL | YES | BTREE | | |
+----------------+------------+------------------------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
6 rows in set (0.00 sec)
select count(*) from `posts`;
+----------+
| count(*) |
+----------+
| 19999 |
+----------+
1 row in set (0.00 sec)
show index from posts;
+-------+------------+--------------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+--------------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| posts | 0 | PRIMARY | 1 | id | A | 16647 | NULL | NULL | | BTREE | | |
| posts | 1 | posts_page_id_index | 1 | page_id | A | 324 | NULL | NULL | | BTREE | | |
| posts | 1 | posts_kind_post_id_index | 1 | kind_post_id | A | 8 | NULL | NULL | | BTREE | | |
| posts | 1 | posts_posted_by_index | 1 | posted_by | A | 31 | NULL | NULL | YES | BTREE | | |
+-------+------------+--------------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
4 rows in set (0.00 sec)
編輯:
該查詢僅是示例。 我真的不想要頁面ID。 一個真實的示例可能是: select * from activities_log left join posts on posts.id = activities_log.post_id where activities_log.page_id = X or posts.page_id = X
不應為每個列使用單獨的索引,而應為每個列使用復合冗余索引
表
activities_log column ( post_id, page_id)
在左位置post_id(連接子句中涉及的列)的左側,在page_id之后。.該列對於避免訪問表數據並從索引表獲取所有數據很有用
您應該記住,查詢可以對涉及的每個表僅使用一個indexc
我不知道您要完成什么。 您有一個left join
,正在從第二個表返回行,因此這些行通常為NULL
。
我最好的猜測-盡管有您的疑問-是您想要具有活動的所有帖子的頁面。 在這種情況下,您可以將查詢的短語設置為:
select p.page_id
from posts p
where exists (select 1
from activities_log al
where p.id = al.post_id
);
至少,這將返回更小的結果集。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.