Оптимизация MYSQL DB - 5 GB. 50 000 000+ строк

123 4
R
На сайте с 03.08.2012
Offline
131
2858

Добрый вечер!

Есть проект - справочник организаций.

Всего организаций - 9 000 000.

Они расположены в таблице: "organization"

Так же есть таблица "organization_category" - где идет связь организации с категориями. Всего около 18 000 000 строк. Т.е. в среднем 1 организация находиться в двух категориях.

Например вот такой запрос выполняется очень долго.

Доходило до 150 секунд на выполнение такого запроса:

SELECT * FROM `organization` WHERE `id` IN (SELECT organization_id FROM `organization_category` WHERE category_id=90) AND `city`=518 AND `status`=1 ORDER BY `name` ASC LIMIT 0,20

Т.е. я выбираю первые 20 организаций, которые находятся в категории = 90 и в городе = 518 со статусом = 1.

Индексы проставил.

EXPLAIN: https://yadi.sk/i/Ys5jRNVb3MoPVR

Ребят, подскажите, пожалуйста, как оптимизировать такой запрос.

Ragnarok
На сайте с 25.06.2010
Offline
226
#1

revered, было что-то подобное, мне помогло разбить на 2 запроса

это вот

SELECT organization_id FROM `organization_category` WHERE category_id=90

выполнить отдельно, получить id через запятую и подставить в первый

...

там баг какой-то, или особенность, такая вложенность очень сильно замедляет

//TODO: перестать откладывать на потом
LEOnidUKG
На сайте с 25.11.2006
Offline
1723
#2

Ну давайте.... какая версия mysql?

В каком типе БД? InnoDB или что?

Почему нет индексов на category_id, status, name?

✅ Мой Телеграм канал по SEO, оптимизации сайтов и серверов: https://t.me/leonidukgLIVE ✅ Качественное и рабочее размещение SEO статей СНГ и Бурж: https://getmanylinks.ru/
S
На сайте с 30.09.2016
Offline
469
#3

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

Отпилю лишнее, прикручу нужное, выправлю кривое. Вытравлю вредителей.
Оптимизайка
На сайте с 11.03.2012
Offline
396
#4

А так?


SELECT * FROM organization
JOIN organization_category on (organization.id = organization_category.organization_id)
WHERE organization_category.category_id=90 AND organization.city=518 AND organization.status=1
ORDER BY organization.name
LIMIT 0,20

Должны быть проиндексированы поля обязательно organization.id, organization_category.organization_id, желательно organization.city, organization.name и возможно, organization_category.category_id

⭐ BotGuard (https://botguard.net) ⭐ — защита вашего сайта от вредоносных ботов, воровства контента, клонирования, спама и хакерских атак!
R
На сайте с 03.08.2012
Offline
131
#5

Версия сервера: 5.5.52-MariaDB - MariaDB Server

Версия протокола: 10

Версия PHP: 5.4.16

InnoDB - тип всех таблиц

Попробовал разделить запросы и произвести настройку сервера (параметры mysql).

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

Вот например если взять такой запрос:

SELECT organization_id FROM `organization_category` WHERE category_id=90

Он бывает выполняется 1 секунду и делает выборку = 100 000 записей из 18 000 000.

При этом индекс category_id стоит.

Ещё, что интересно. Когда выполняю такой запрос в PHPmyadmin - выдает время на выполнение 0.05 секунд примерно.

А когда выполняю в PHP - первый раз выдает 0.5-1 сек, а потом когда берет с кеша уже уже менее 0.05 сек.

В PHP считаю время так:

$start = microtime(TRUE);
$res = mysqli_query($this->conn, $query);
$timer = microtime(TRUE) - $start;

И вот замечаю, что когда в phpmyadmin выполняю запрос: страница вроде грузиться долго, около 1 сек, а потом выдает что запрос выполнен за 0.05 сек.

LEOnidUKG
На сайте с 25.11.2006
Offline
1723
#6
Версия сервера: 5.5.52-MariaDB

рекомендую обновить хотя бы до 10,1 т.к. там ОЧЕНЬ много вещей сделано для innoDB в плане оптимизации.

И нагрузка на сервер какая? Может диск тупо не справляется?

Также у вас какие настройки для innodb? Вы mysqltunner запускали, что он говорит?

D
На сайте с 07.11.2000
Offline
219
#7
revered:
PHPmyadmin - выдает время на выполнение 0.05 секунд примерно.
А когда выполняю в PHP - первый раз выдает 0.5-1 сек, а потом когда берет с кеша уже уже менее 0.05 сек.

В PHPmyadmin может из кеша подтянулось (то, что делали в PHP)?

totamon
На сайте с 12.05.2007
Offline
437
#8
revered:
Он бывает выполняется 1 секунду и делает выборку = 100 000 записей из 18 000 000.

зачем вам 100000 записей? в PHPmyadmin автоматически бьет на страницы...

Домены и хостинг https://8fn.ru/regru | Дедик от 3000р https://8fn.ru/73 | VPS в Москве https://8fn.ru/72 | Лучшие ВПС, ТП огонь, все страны! https://8fn.ru/inferno | ХОСТИНГ №1 РОССИИ https://8fn.ru/beget
W
На сайте с 18.09.2006
Offline
86
#9

Еще можно копнуть в другом направлении , если у вас в среднем на город гораздо меньше 100к организаций, то может стоит сперва вытаскивать их, список компаний по городу.

и все равно id IN (...), медленно будет работать даже при 1к, по сравнению с некоторыми другими решениями, опять же нужно исходить из содержимого базы, желательно сперва статистические данные изучить , как например описано выше, количество организаций на город и т.п.

B
На сайте с 13.02.2008
Offline
262
#10
revered:
Он бывает выполняется 1 секунду и делает выборку = 100 000 записей из 18 000 000.
При этом индекс category_id стоит.

Это нормально. Что ж вы еще хотите? 100 тыщ записей ведь надо еще перегнать куда то. На это и уходит время. Сделайте в том же запросе (без сортировки) limit на 100 записей и время скорей всего сократится до сотых долей секунды.

123 4

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий