Я - парень MSSQL и не использовал mysql, но концепции должны быть одинаковыми.
Во-первых, вы можете удалить группу и упорядочить и закомментировать все таблицы, кроме первого "пользователя".Также закомментируйте все столбцы удаленных таблиц.Как у меня ниже.
SELECT s.id AS s__id,
s.dname AS s__dname,
s.gender AS s__gender,
s.height AS s__height,
s.dob AS s__dob
-- s3.id AS s3__id,
-- s3.code AS s3__code,
-- s3.name_geo AS s3__name_geo,
-- s4.id AS s4__id,
-- s4.name_geo AS s4__name_geo,
-- s5.id AS s5__id,
-- s6.id AS s6__id,
-- s7.id AS s7__id,
-- s8.id AS s8__id,
-- s9.id AS s9__id
FROM user s --LEFT JOIN
-- country s3 ON s.country_id = s3.id LEFT JOIN
-- city s4 ON s.city_id = s4.id LEFT JOIN
-- block s5 ON ((s.id = s5.blocked_id AND s5.blocker_id = '1')) LEFT JOIN
-- favorite s6 ON ((s.id = s6.favorited_id AND s6.favoriter_id = '1')) LEFT JOIN
-- favorite s7 ON ((s.id = s7.favoriter_id AND s7.favorited_id = '1')) LEFT JOIN
-- message s8 ON ((s.id = s8.sender_id AND s8.receiver_id = '1' AND s8.read_at IS NULL)) LEFT JOIN
-- message s9 ON (((s.id = s9.sender_id AND s9.receiver_id = '1') OR (s.id = s9.receiver_id AND s9.sender_id = '1')))
WHERE (s.id IN ('22', '36', '53', '105', '152', '156', '169', '182', '186', '192', '201', '215', '252', '287', '288', '321', '330', '351', '366', '399'))
Запустите запрос и запишите время.Затем добавьте одну таблицу и ее столбцы обратно и запускайте ее до тех пор, пока не найдете, какая из них приводит к значительному замедлению.
SELECT s.id AS s__id,
s.dname AS s__dname,
s.gender AS s__gender,
s.height AS s__height,
s.dob AS s__dob,
s3.id AS s3__id,
s3.code AS s3__code,
s3.name_geo AS s3__name_geo
-- s4.id AS s4__id,
-- s4.name_geo AS s4__name_geo,
-- s5.id AS s5__id,
-- s6.id AS s6__id,
-- s7.id AS s7__id,
-- s8.id AS s8__id,
-- s9.id AS s9__id
FROM user s LEFT JOIN
country s3 ON s.country_id = s3.id --LEFT JOIN
-- city s4 ON s.city_id = s4.id LEFT JOIN
-- block s5 ON ((s.id = s5.blocked_id AND s5.blocker_id = '1')) LEFT JOIN
-- favorite s6 ON ((s.id = s6.favorited_id AND s6.favoriter_id = '1')) LEFT JOIN
-- favorite s7 ON ((s.id = s7.favoriter_id AND s7.favorited_id = '1')) LEFT JOIN
-- message s8 ON ((s.id = s8.sender_id AND s8.receiver_id = '1' AND s8.read_at IS NULL)) LEFT JOIN
-- message s9 ON (((s.id = s9.sender_id AND s9.receiver_id = '1') OR (s.id = s9.receiver_id AND s9.sender_id = '1')))
WHERE (s.id IN ('22', '36', '53', '105', '152', '156', '169', '182', '186', '192', '201', '215', '252', '287', '288', '321', '330', '351', '366', '399'))
Я предполагаю, что это будет блок, а также избранное и соединения сообщений.что дает вам удар по производительности (тот, у которого наибольшее количество строк будет самым большим хитом).
Для таблицы блоков: Можете ли вы удалить один из индексов и изменить другой, чтобы он был чем-то похожим на(Я не уверен в синтаксисе, но вы поймете смысл)
INDEX blocker_id_idx (blocker_id,blocked_id),
и попробуйте его с измененным порядком столбцов, чтобы найти порядок ведьм лучше для вашего запроса
INDEX blocker_id_idx (blocked_id,blocker_id),
Для любимой таблицы измените индексы на
INDEX favoriter_id_idx (favoriter_id,favorited_id),
INDEX favorited_id_idx (favorited_id,favoriter_id),
Еще раз попробуйте с перестановкой столбцов, чтобы найти, которые дают лучшую производительность.Сделайте то же самое для индексов сообщений.
Сделайте это и дайте мне знать, если что-то улучшилось.Есть несколько других вещей, которые можно сделать, чтобы улучшить его дальше.- РЕДАКТИРОВАТЬ: Кажется, я солгал о нескольких других вещах, то, что я намеревался, не имело бы никакого значения.Но я могу ускорить ваш первый запрос, который приведен ниже.
РЕДАКТИРОВАТЬ Это для вашего первого запроса выбора.
Этот запрос довольно длинный, но я хотел показать вам, как работают индексыВы можете сделать свой собственный.
Допустим, таблица содержит 100 000 строк.
Когда вы выбираете из него, это общий процесс, который он займет.
- Существуют ли какие-либо индексы, которые покрывают или в основном покрывают нужные мне столбцы.(В вашем случае, нет, нет.)
- Поэтому используйте Первичный индекс и сканируйте каждую строку в таблице, чтобы проверить на совпадение.
- Каждая строка в таблице должначитать с диска, чтобы найти, какие столбцы соответствуют вашим критериям.Таким образом, чтобы вернуть примерно 10000 строк (это предположение), соответствующих вашим данным, ядро базы данных прочитало все 100 000 строк.
У вас есть 20 лучших в вашем запросе, поэтому он ограничитколичество строк, которые двигатель будет читать с диска.Пример
- чтение строки 1: совпадение, поэтому добавьте к результату
- чтение строки 2: нет совпадений - пропуск
- чтение строки 3: нет совпадений - пропуск
- чтение строки 4: совпадение, поэтому добавьте к результату.
- останов после 20 идентифицированных строк
Возможно, вы прочитали около 5000 строк с диска, чтобы вернуть 20.
Нам нужно создать индекс, который поможет нам читать как можно меньше записей из таблицы / диска, но при этом получать строки, которые нам нужны.Итак, пошли.
Ваш запрос использует 4 фильтра для доступа к данным.
s.gender = 'female' AND
s.marital_status = 'single' AND
s.smokes = 'no' AND
s.deleted_at IS NULL
Теперь нам нужно определить, какой фильтр сам по себе вернет наименьшее количество строк.Я не могу сказать, потому что у меня нет никаких данных, но это то, что я предполагаю, чтобы быть в вашей таблице.
Гендерный столбец поддерживает 2 значения, и было бы справедливо оценить, что половина записей в вашей базе данных - мужчины, а другая - женщины, поэтому необходимый вам фильтр вернет приблизительно 50 000 строк.
Теперь для семейного положения, поддерживает четыре значения, поэтому, если мы скажем, что данные имеют одинаковый разброс, это будет означать, что мы получим примерно 25 000 строк назад.Конечно, это зависит от фактических данных, и я бы сказал, что не слишком много овдовевших данных, поэтому лучшая оценка может составить 30% от остальных трех.Итак, допустим, 30 000 записей помечены как одиночные.
Теперь для столбца дымов.Я читал, что здесь, в Австралии, около 10% людей курят, что довольно мало по сравнению с другими странами.Так скажем, 25% или курят или курят иногда.Это оставляет нам около 75 000 некурящих.
Теперь для последнего столбца удалено.Честное предположение с моей стороны, но допустим, 5% помечены как удаленные.Это оставляет нам около 95 000 строк.
Итак, в заключение (помните, что это все чисто догадки с моей стороны, ваши данные могут отличаться) Пол 50 000 строк или 50% Семейное положение 30 000 строк или 30% курит75 000 строк или 75% удалено 95 000 строк или 95%
Итак, если мы создадим индекс с четырьмя столбцами, использующий тот, который сначала возвращает наименьшее количество строк, мы получим следующее
INDEX index01_idx (marital_status,gender,smokes,deleted_at),
Теперь это то, что произойдет, когда мы запустим select.
- Сервер найдет индекс, охватывающий все столбцы в предложении WHERE
- . Он сузитнабор результатов равен 30 000 «одиночных» записей.
- Из этих 30 000 50% будут женщины, которые оставят 15 000 записей
- Из этих 15 000 75% не будут курить, оставляя 11 250 записей
- Из этих 11 250, 95% не будут удалены,
Это оставляет нам чуть более 10 000 записей из 100 000, которые мы определили как записи, которые мы хотим, но еще не прочиталис диска.У вас также есть ограничение 20 в запросе, поэтому ядру базы данных просто нужно прочитать первые 20 из 10000 и вернуть результат.Его супер быстрый, жесткий диск будет любить вас, и страшный администратор базы данных даже бормотать и хрюкать с одобрением.