Оптимизировать запрос mysql на Python

#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 . я опубликовал некоторые предложения для индекса .. ответ обновлен .. если у вас нет индекса или нет допустимого выборочного индекса слева направо .. доступ к данным таблицы может оказать соответствующее влияние на производительность