MySQL - Большая база данных, улучшить время поиска - PullRequest
0 голосов
/ 09 июля 2019

У меня есть две довольно большие таблицы (threads и posts), которые содержат тонну сообщений на форуме. Мне действительно нужно улучшить время поиска. Даже обычный поиск, где COLUMN = VALUE займет 15 секунд. Выполнение LIKE часто приводит к сбою всего сайта (тайм-аут).

Вот фотография моего сайта и две таблицы: enter image description here

Таблица threads содержит около 430 000 строк.

Таблица posts содержит около 2 700 000 строк.

И мне нужно объединить их в запросе, чтобы получить желаемые результаты.

Пока не беспокойтесь о окнах поиска на сайте. Давайте просто начнем с этого запроса и начнем сначала его улучшать.

SELECT p.id, t.id, t.title, t.threadstarter, t.replies, t.views, t.board, p.dateposted FROM threads t
JOIN posts p
ON t.id = p.threadid
WHERE t.title = 'sell'
GROUP BY t.id

Этот запрос займет около 15 секунд, чтобы получить все темы и сообщения с заголовком темы "продать". Как бы я улучшил это, сделав это всего секунду или две? Возможно ли это даже с MySQL в двух таблицах с этими размерами?

И с этого момента я должен был бы сделать LIKE (если нет другого метода). Потому что пользователи на сайте, скорее всего, не будут искать точное совпадение. И я хотел бы включить любой заголовок, который включает в себя мир «продать». Итак, это было бы так:

SELECT p.id, t.id, t.title, t.threadstarter, t.replies, t.views, t.board, p.dateposted FROM threads t
JOIN posts p
ON t.id = p.threadid
WHERE t.title LIKE '%sell%'
GROUP BY t.id

Что я даже не собираюсь беспокоить измерения. Это сбой веб-сайта (слишком долго, чтобы выполнить). Так что этот действительно (!) Нуждается в улучшении.

Как мне вообще подойти к этому? Должен ли я даже использовать MySQL? Какие варианты у меня есть? Я не хочу, чтобы пользователь сидел и ждал 30-300 секунд до завершения запроса. Максимум 5 секунд.

Возможно ли это с такими большими таблицами? Я слышал, что использование "MATCH" и "AGAINST" может быть лучше, чем "COLUMN", как "VALUE". Но тогда мне нужно сделать все столбцы свободными. Есть ли недостатки в этом?

Если есть кто-нибудь, кто работал с базой данных MySQL на ~ 3 миллиона строк, то, пожалуйста, дайте мне знать, как вы справились (если вы это сделали).

Ответы [ 4 ]

0 голосов
/ 10 июля 2019

LIKE с подстановочным знаком должен отсканировать все 430 000 строк:

WHERE t.title LIKE '%sell%'

Изменить на:

WHERE MATCH(t.title) AGAINST('+sell' IN BOOLEAN MODE)

и иметь

FULLTEXT(title)

При такой настройке запрос может идти непосредственно к нескольким строкам, в которых есть «слово» sell.

Предупреждение: Существуют ограничения на то, что FULLTEXT может искать - только «слова», а не "стоп-слова", только слова определенной минимальной длины и т. д.

0 голосов
/ 09 июля 2019

Правильный способ выражения вашего первого запроса:

SELECT p.id, t.id, t.title, t.threadstarter, t.replies, t.views, t.board, p.dateposted
FROM threads t JOIN
     posts p
     ON t.id = p.threadid
WHERE t.title = 'sell' AND
      p.dateposted = (SELECT MIN(p2.dateposted) FROM posts p2 WHERE p2.threadid = p.threadid);

Это избавляет от GROUP BY, что может повысить производительность.В частности, вам нужны индексы:

  • threads(title, id)
  • posts(threadid, dateposted)
0 голосов
/ 09 июля 2019
0 голосов
/ 09 июля 2019

Используйте INDEX.Просто попробуйте создать индекс для одной из таблиц, в которой есть больше записей, или для мастера, хотя его внутреннее объединение все же облегчит внутреннее объединение двух.

Кроме того, я просто понимаю, что использование group by без агрегации означает select *.. в запросе.

    CREATE  INDEX Index_NAME ON 
       threads(title);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...