Хорошо индексированный MySQL запрос занимает много времени для выполнения. EXPLAIN показывает 3м строки. Можно ли его ускорить или улучшить? - PullRequest
2 голосов
/ 03 марта 2020

У меня есть база данных с более чем 100 миллионами строк данных комментариев Reddit в формате:

{
 author: redditauthor1,
 body: example comment,
 subreddit: /r/funny,
 ....
}

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

У меня есть 4 индекса для этой таблицы. Причина в том, что я пока только планирую читать из этого. Индексы выглядят так:

CREATE INDEX idx_subreddit
ON comments(subreddit);

CREATE INDEX idx_author
ON comments(author);

CREATE INDEX idx_authsub
ON comments(author, subreddit);

CREATE INDEX idx_subauth
ON comments(subreddit, author);

Я также пытался просто сузить его до индекса subreddit, автора без каких-либо улучшений. Я еще больше сужаю свой поиск, удаляя [удаленных] пользователей из списка строк. Мой запрос выглядит следующим образом:

SELECT author, subreddit, count(*) as numcomments 
from comments
WHERE author IN (SELECT author FROM comments WHERE subreddit="politics"  AND author != "[deleted]")
group by author, subreddit
ORDER BY author
LIMIT 100
;

Согласно моему плану объяснения, это возвращает 3 миллиона строк, что ожидается от набора данных почти 100 ГБ.

mysqlexplain

Запрос выполняется более 300 секунд для больших поддредитетов, таких как / r / policy . Меньшие с меньшей активностью запускаются в секунду или меньше. Что я могу сделать, чтобы улучшить время выполнения? Я попытался выполнить запрос через Ever SQL и использовать указанный запрос, а также один подредит , автор составной индекс, который они рекомендовали, но на самом деле это ухудшило время выполнения. Я знаю, что есть сторонние варианты, такие как pushShift API, который использует Google BigQuery, но, поскольку я хотел бы работать над этим в автономном режиме, я хочу сделать все это локально. Наконец, я подумал о том, чтобы просто получить все комментарии и «посчитать» их самому, вместо того, чтобы использовать метод и группу mySql count (*), но даже при этом для получения всех комментариев требуется время (15 миллионов). ) что я должен был бы обработать на заднем конце. Есть ли этому решение? Что-то вроде системы кеширования Redis? Разметка? Я бы sh, чтобы получить этот запрос менее 3 секунд, если это возможно. Любые отзывы приветствуются.


По предложению пользователя я выполнил объяснение по этому запросу:


SELECT x.author
     , x.subreddit
     , COUNT(*) numcomments 
  FROM comments x
  JOIN  
     ( SELECT author 
         FROM comments 
        WHERE subreddit = "politics"  
          AND author != "[deleted]"
     ) y
    ON y.author = x.author
 GROUP 
    BY x.author
     , x.subreddit;

и ОБЪЯСНЕНИЕ произвело это: explain2

1 Ответ

1 голос
/ 03 марта 2020

Переместить критерии непосредственно в основной запрос. Добавляя два выбора, вы делаете по крайней мере вдвое больше работы. Удачи.

SELECT author, subreddit, count(*) as numcomments 
from comments
WHERE subreddit="politics"  AND author != "[deleted]"
group by author, subreddit
LIMIT 100
;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...