MySQL JOIN занимает более 10 секунд - PullRequest
0 голосов
/ 14 мая 2019
Короче

, есть две таблицы: activities_log со строками 3,3M и posts со строками 20K.Когда к ним присоединяется какой-то запрос, это занимает больше 15 секунд !!!(╥﹏╥)

Что я делаю не так?Что я мог сделать, чтобы оптимизировать?

Он работает на этом сервере:

  • mysql Ver 14.14 Distrib 5.7.26, для Linux (x86_64) с использованием оболочки EditLine
  • Капли Digitalocean / 4 ГБ памяти(4 ГБ подкачки) / 60 ГБ Диск
  • Ubuntu 18.04.1 LTS (GNU / Linux 4.15.0-43-generic 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)

РЕДАКТИРОВАТЬ:

Этот запрос является лишь примером.Я действительно не хочу идентификаторы страниц.Реальный пример может быть: 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

Ответы [ 2 ]

1 голос
/ 14 мая 2019

Я не могу понять, чего вы пытаетесь достичь. У вас есть left join и вы возвращаете строки из таблицы second , поэтому они часто могут быть NULL.

Мое лучшее предположение - несмотря на ваш запрос - то, что вам нужны страницы всех постов, которые имеют активность. Если это так, то вы можете сформулировать запрос как:

select p.page_id
from posts p
where exists (select 1
              from activities_log al
              where p.id = al.post_id
             );

По крайней мере, это вернет намного меньший набор результатов.

1 голос
/ 14 мая 2019

Вместо отдельных индексов для каждого столбца вы должны использовать составной избыточный индекс для

таблицы

  activities_log    column  ( post_id, page_id)

с левой позицией post_id (столбец, включенный в предложение объединения) и после page_id.Этот столбец полезен для предотвращения доступа к данным таблицы и получения всех данных из таблицы индексов

. Следует учитывать, что запрос может использовать только один индекс для каждой задействованной таблицы

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...