簡體   English   中英

MySQL JOIN花費超過10秒

[英]MySQL JOIN take more than 10 seconds

簡而言之,有兩個表, activities_log有330萬行,而posts有20K行。 當一些查詢加入他們的過程超過15秒! (╥﹏╥)

我做錯了什么? 我可以做些什么來優化?

它正在此服務器上運行:

  • 適用於Linux(x86_64),使用EditLine包裝器的mysql Ver 14.14 Distrib 5.7.26
  • Digitalocean小滴/ 4 GB內存(4 GB交換)/ 60 GB磁盤
  • Ubuntu 18.04.1 LTS(GNU / Linux 4.15.0-43-通用x86_64)
# 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM