Как улучшить производительность базы данных Mysql без изменения структуры БД

У меня есть база данных, которая уже используется, и я должен улучшить производительность системы, которая использует эту базу данных.

Есть 2 основных запроса, выполняющихся около 1000 раз в цикле, и эти запросы имеют внутренние объединения с 3 другими таблицами каждый. Это, в свою очередь, делает систему очень медленной.
На самом деле я пытался удалить запрос из цикла, извлечь все данные только один раз и обработать его в PHP. Но это создает большую нагрузку на память (RAM), и система зависает, если 2 или более клиентов пытаются использовать систему.

В таблицах содержится много данных даже после удаления просроченных данных.
Я приложил запрос ниже.
Кто-нибудь может мне помочь с этим вопросом?

select * from inventory
where   (region_id = 38 or region_id = -1)
and (tour_opp_id = 410 or tour_opp_id = -1)
and room_plan_id = 141 and meal_plan_id = 1 and bed_type_id = 1 and hotel_id = 1059
and  FIND_IN_SET(supplier_code, 'QOA,QTE,QM,TEST,TEST1,MQE1,MQE3,PERR,QKT')
and ( ('2014-11-14' between from_date and to_date) )
order by hotel_id desc ,supplier_code desc, region_id desc,tour_opp_id desc,inventory.inventory_id descSELECT * ,pinfo.fri as pi_day_fri,pinfoadd.fri as pa_day_fri,pinfochld.fri as pc_day_fri
FROM `profit_markup`
inner join profit_markup_info as pinfo on pinfo.profit_id = profit_markup.profit_markup_id
inner join profit_markup_add_info as pinfoadd on pinfoadd.profit_id = profit_markup.profit_markup_id
inner join profit_markup_child_info as pinfochld on pinfochld.profit_id = profit_markup.profit_markup_id
where  profit_markup.hotel_id = 1059 and (`booking_channel` = 1 or `booking_channel` = 2)
and (`rate_region` = -1 or `rate_region` = 128)
and ( ( period_from <= '2014-11-14' and period_to >= '2014-11-14' ) )
ORDER BY profit_markup.hotel_id DESC,supplier_code desc, rate_region desc,operators_list desc, profit_markup_id DESC

0

Решение

Так как мы не видели ваши SHOW CREATE TABLES; а также EXPLAIN EXTENDED планировать трудно дать 1 ответ

Но, вообще говоря, в отношении вашего запроса «Кстати, я переписал ниже»

SELECT
hotel_id, supplier_code, region_id, tour_opp_id, inventory_id
FROM
inventory
WHERE
region_id IN (38, -1)
AND tour_opp_id IN (410, -1)
AND room_plan_id IN (141, 1)
AND bed_type_id IN (1, 1059)
AND supplier_code IN ('QOA', 'QTE', 'QM', 'TEST', 'TEST1', 'MQE1', 'MQE3', 'PERR', 'QKT')
AND ('2014-11-14' BETWEEN from_date AND to_date )
ORDER BY
hotel_id DESC, supplier_code DESC, region_id DESC, tour_opp_id DESC, inventory_id DESC
  1. Не использовать * чтобы получить все столбцы. Вы должны перечислить столбец, который вам действительно нужен. С помощью * это просто ленивый способ написания запроса. ограничение столбцов будет ограничивать размер данных, который выбирается.

  2. Как часто записи в инвентаре обновляются / вставляются / удаляются? Если не слишком часто, то вы можете использовать рассмотреть возможность использования SQL_CACHE, Однако кэширование запроса вызовет у вас проблемы, если вы его используете, и таблица инвентаризации обновляется очень часто. Кроме того, чтобы использовать кеш запросов, необходимо проверить значение query_cache_type на вашем сервере. SHOW GLOBAL VARIABLES LIKE 'query_cache_type';, Если установлено значение «0», то функция кэширования отключена и SQL_CACHE будут игнорироваться Если установлено значение 1, то сервер будет кэшировать все запросы, если вы не скажете, что это не слишком NO_SQL_CACHE, Если для параметра задано значение 2, MySQL будет кэшировать запрос только в том случае, если используется предложение SQL_CACHE. вот документация о query_cache_type

  3. Если у вас есть указатель на следующие столбцы в этом порядке, это поможет вам (hotel_id, supplier_code, region_id, tour_opp_id, inventory_id)

    ALTER TABLE inventory
    ADD INDEX (hotel_id, supplier_code, region_id, tour_opp_id, inventory_id);
    
  4. Если возможно увеличить sort_buffer_size на вашем сервере, поскольку, скорее всего, вы выдаете здесь вопрос о том, что вы делаете слишком много сортировки.

Что касается второго запроса «Кстати, я переписал ниже»

SELECT
*, pinfo.fri as pi_day_fri,
pinfoadd.fri as pa_day_fri,
pinfochld.fri as pc_day_fri
FROM
profit_markup
INNER JOIN
profit_markup_info AS pinfo ON pinfo.profit_id = profit_markup.profit_markup_id
INNER JOIN
profit_markup_add_info AS pinfoadd ON pinfoadd.profit_id = profit_markup.profit_markup_id
INNER JOIN
profit_markup_child_info AS pinfochld ON pinfochld.profit_id = profit_markup.profit_markup_id
WHERE
profit_markup.hotel_id = 1059
AND booking_channel IN (1, 2)
AND rate_region IN (-1, 128)
AND period_from <= '2014-11-14'
AND period_to >= '2014-11-14'
ORDER BY
profit_markup.hotel_id DESC, supplier_code DESC, rate_region DESC,
operators_list DESC, profit_markup_id DESC
  1. Снова исключить использование * из вашего запроса

  2. Убедитесь, что следующие столбцы имеют одинаковый тип / сопоставление и одинаковый размер. pinfo.profit_id, profit_markup.profit_markup_id, pinfoadd.profit_id, pinfochld.profit_id и у каждого должен быть индекс на каждой таблице. Если столбцы имеют разные типы, MySQL будет каждый раз преобразовывать данные, чтобы объединить записи. Даже если у вас есть индекс, он будет медленнее. Кроме того, если эти столбцы имеют тип символов (например, VARCHAR ()), убедитесь, что они относятся к CHAR() с сопоставлением latin1_general_ci так как это будет быстрее для поиска ID, но если вы используете INT (), даже лучше.

  3. Используйте 3-й и 4-й приемы, которые я перечислил для предыдущего запроса

  4. Попробуйте использовать STRAIGHT_JOIN: «Вы должны знать, что вы здесь делаете, иначе это вас укусит!» Вот хорошая ветка об этом Когда использовать STRAIGHT_JOIN с MySQL

Надеюсь, это поможет.

0

Другие решения

Для первого запроса я не уверен, что вы можете многое сделать (при условии, что вы уже проиндексировали поля, по которым вы упорядочиваете), кроме замены * на имена столбцов (не ожидайте, что это резко повысит производительность).

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

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

(Если ничего не получается, то лучше всего использовать memcache … Хотя лично я никогда не делал этого)

0

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

Для обоих запросов первый проверочный индекс доступен для столбцов предложения WHERE и ON (Join), если индекс отсутствует, необходимо добавить индекс для повышения производительности запроса.

Проверьте объяснение плоскости перед созданием индекса.

По возможности покажите мне плоскость объяснения обоих запросов, которая поможет нам.

0
По вопросам рекламы [email protected]