#python #mysql #mysql-connector-python
#python #mysql #mysql-connector-python
Вопрос:
Я подключаюсь к базе данных mysql с помощью mysql-connector на python. При обычном запуске событий мне не придется обрабатывать более 1000 строк, но иногда мне может потребоваться обработать более 20 тысяч строк данных, и именно здесь мой запрос становится очень медленным и время ожидания истекает. Я попытался использовать итератор в mysql-connector, чтобы ограничить объем, который я обрабатываю в данный момент времени, но, похоже, это реализовано только для MySQLdb в py.
SELECT
ROUND(311.30004 - (20.110938 * temp.value)
- (2.012626 * hum.value) - (2.006346 * airspeed.value)
(0.4059 * POWER(temp.value, 2) (0.006604 * POWER(hum.value, 2))
(3.151145 * POWER(airspeed.value, 2) (0.05555 * temp.value * hum.value)
- (0.37037 * temp.value * airspeed.value) (0.03968 * hum.value * airspeed.value))), 2)
AS value, temp.time, temp.x, temp.y, temp.z, temp.round_id, 'predicted_frequency', temp.round_number, temp.day_of_production
FROM round_data_temperature AS temp
INNER JOIN round_data_humidity AS hum
ON temp.round_number = hum.round_number
AND temp.x = hum.x
AND temp.y = hum.y AND DATE_FORMAT(temp.time, '%Y-%m-%d %H:%i:00') = DATE_FORMAT(hum.time, '%Y-%m-%d %H:%i:00')
INNER JOIN round_data_airspeed AS airspeed
ON temp.round_number = airspeed.round_number
AND temp.x = airspeed.x AND temp.y = airspeed.y
AND DATE_FORMAT(temp.time, '%Y-%m-%d %H:%i:00') = DATE_FORMAT(airspeed.time, '%Y-%m-%d %H:%i:00')
WHERE temp.round_id ='xxxxx'
Этот код выполняется очень быстро только в mysql, но очень медленно и время ожидания в mysql-connector в python с более чем 20 тысячами строк, поэтому я решил вставить немедленно, чтобы избежать выбора очень больших пакетов данных в python. Я сделал следующее:
INSERT INTO round_data_pf (value, time, x, y, z, round_id, observable_name, round_number, day_of_production)
SELECT
ROUND(311.30004 - (20.110938 * temp.value)
- (2.012626 * hum.value) - (2.006346 * airspeed.value)
(0.4059 * POWER(temp.value, 2) (0.006604 * POWER(hum.value, 2))
(3.151145 * POWER(airspeed.value, 2) (0.05555 * temp.value * hum.value)
- (0.37037 * temp.value * airspeed.value) (0.03968 * hum.value * airspeed.value))), 2)
AS value, temp.time, temp.x, temp.y, temp.z, temp.round_id, 'pf', temp.round_number, temp.day_of_production
FROM round_data_temperature AS temp
INNER JOIN round_data_humidity AS hum
ON temp.round_number = hum.round_number
AND temp.x = hum.x
AND temp.y = hum.y
AND DATE_FORMAT(temp.time, '%Y-%m-%d %H:%i:00') = DATE_FORMAT(hum.time, '%Y-%m-%d %H:%i:00')
INNER JOIN round_data_airspeed AS airspeed
ON temp.round_number = airspeed.round_number
AND temp.x = airspeed.x
AND temp.y = airspeed.y
AND DATE_FORMAT(temp.time, '%Y-%m-%d %H:%i:00') = DATE_FORMAT(airspeed.time, '%Y-%m-%d %H:%i:00')
WHERE temp.round_id ='xxxxx'
Время ожидания этого кода истекает как в mysql, так и в mysql-connector в python, когда у меня около 20 тыс. строк данных.
Я хочу оптимизировать код, чтобы он быстрее выбирал и вставлял, когда у меня есть, скажем, 20 тысяч строк.
Комментарии:
1. Не очень понятно в вашем вопросе, быстро ли это в mysql по сравнению с медленным в python для ТОГО ЖЕ объема данных?
2. В mysql без вставки он выполняется менее чем за 2 секунды с примерно 20 тыс. строк данных. При вставке время ожидания истекает. В python время ожидания истекает в обоих случаях с примерно 20 тысячами строк данных.
3. 20 Тысяч строк — это крошечный объем данных. Если запрос выполняется медленно, это означает, что отсутствуют индексы или что запрос не позволяет серверу использовать какие-либо индексы. Серверу, возможно, придется сканировать всю таблицу, чтобы получить эти 100 или 20 тысяч строк
4. Это также зависит от распределения данных — сколько строк он возвращает из ВСЕХ строк? ЕСЛИ больше 35% или около того, оптимизатор предпочтет сканирование таблицы, независимо от того, какие у вас индексы.
5. Это
DATE_FORMAT(temp.time, '%Y-%m-%d %H:%i:00') = DATE_FORMAT(airspeed.time, '%Y-%m-%d %H:%i:00')
не позволяет серверу использовать индексы ни в одном изtime
столбцов. Это потому, что индексы используют исходные значения, а не форматированные строки, которые этот запрос хочет сравнить. Это означает, что серверу придется отформатировать и сравнить все строки, созданные в соответствии с другими условиями объединения
Ответ №1:
убедитесь, что у вас есть правильный индекс на
table round_data_temperature composite index on columns (round_id, round_number, x, y, time)
table round_data_humidity composite index on columns (round_number, x, y time)
table round_data_airspeed comoosite index on clumns (round_number, x, y,time )
Вы должны учитывать тот факт, что каждая таблица, участвующая в связи, может использовать только один индекс .. если у вас нет индекса в таблице, таблица полностью сканируется.
Разница между индексом с одним столбцом и составным индексом заключается в том, что все столбцы (слева направо), присутствующие в индексе, используются для фильтрации запроса, избегая доступа к данным таблицы, поэтому в определенной ситуации использование составного индекса (правильно определенного) может значительно улучшить запрос..
Комментарии:
1. Я проиндексировал свои строки, но не как составные, помимо time. Сейчас я буду индексировать время, но есть ли разница между обычным индексом и составным индексом? Если это так, я сделаю их составными индексами.
2. @J.Ewa запрос не может использовать какие-либо индексы вовремя, как это написано. Если у вас нет индексов, запрос полностью сканирует обе таблицы
3. @J.Ewa . я опубликовал некоторые предложения для индекса .. ответ обновлен .. если у вас нет индекса или нет допустимого выборочного индекса слева направо .. доступ к данным таблицы может оказать соответствующее влияние на производительность