SQLalchemy - pymssql - pandas всегда медленный или я делаю это неправильно?

вопрос

Я пытаюсь прочитать таблицу в MS SQL Server, используя python, в частности SQLalchemy, pymssql и pandas.read_sql. Я хочу выполнить запрос, поместить результаты в Dataframe pandas и продолжить мой день с разумной скоростью, но довольно простой запрос (вывод = 100 МБ) занимает почти 5-10 минут при подключении к локальной сети с использованием Ethernet Кабели - нет Wi-Fi в поле зрения.

Результирующий кадр данных с 3 столбцами и 3214086 записями занял колоссальные 423 секунды. Следующая информация ():

Int64Index: 3214086 entries, 0 to 3214085
Data columns (total 3 columns):
DateTime    datetime64[ns]
TagName     object
Value       float64
dtypes: datetime64[ns](1), float64(1), object(1)
memory usage: 98.1+ MB
None

Если моя математика верна, 100 МБ за 423 секунды - это около 230 КБ / с, что, по-моему, из-за Ethernet-соединения мучительно медленно. Узкое место должно быть в самом сервере sql


Информация о запросе

Сам сервер SQL представляет собой установку Wonderware, которая может иметь или не иметь какое-либо отношение к нему. В следующем запросе я запрашиваю значения 6 разных тегов за промежуток времени в 1 месяц, где разрешение составляет 5000 мс или 5 секунд.

Вот как выглядит сам запрос:

sql_query = '''
SELECT DateTime, TagName, Value

    FROM Runtime.dbo.AnalogHistory

    WHERE
        DateTime BETWEEN '2014-05-26 00:00' AND '2014-06-26 00:00'
    AND 
        TagName IN (
            'Tag1.ActualValue', 
            'Tag2.ActualValue', 
            'Tag3.ActualValue', 
            'Tag4.ActualValue', 
            'Tag5.ActualValue', 
            'Tag6.ActualValue')
    AND
        wwRetrievalMode = 'Cyclic'
    AND
        wwResolution = 5000
'''

И, наконец, функция executeQuery:

import pandas as pd
import pymssql
import sqlalchemy

def executeQuery(sql_query):
    connection_string = 'mssql+pymssql://user:password@server'
    engine = sqlalchemy.create_engine(connection_string)

    df = pd.read_sql(sql_query, engine)

    if 'DateTime' in df.columns:
        df.DateTime = pd.to_datetime(df.DateTime, infer_datetime_format=True)

    return df

Вопрос

Что тут происходит? Это ограничение в одном из пакетов, которые я использую, или я могу ускорить работу с тем, что у меня есть?

Этот вопрос, по- видимому, связан с тем, что ОП пытался записать на сервер SQL. Там говорится, что быстрее использовать "BULK INSERT" вместо панд, использующих файл.csv, но это нереальный вариант для чтения с сервера SQL. Должен ли я иметь каталог, содержащий файлы.csv со всеми датами / временем и всеми тегами!? Это отрицательно скажется на использовании сервера sql, не так ли?

1 ответ

Я полагаю, вы звоните executeQuery() Функция в цикле - довольно много раз, и каждый раз вы заново создаете движок SQLAlchemy, который замедляет работу.

Поэтому попробуйте создать соединение с БД один раз и использовать его несколько раз:

import pandas as pd
import pymssql
import sqlalchemy

connection_string = 'mssql+pymssql://user:password@server'
engine = sqlalchemy.create_engine(connection_string)

def executeQuery(sql_query, engine=engine):
    df = pd.read_sql(sql_query, engine)

    # i'm not sure that you really need it ...
    if 'DateTime' in df.columns:
        df.DateTime = pd.to_datetime(df.DateTime, infer_datetime_format=True)

    return df

PS если ваш DateTime столбец на стороне MS SQL имеет тип данных DateTime, SQLAlchemy должен сопоставить его с Python datetime тип. Так что в конце это уже должно быть np.datetime64...

Если вы звоните по телефону один или несколько раз, я бы сделал следующее:

  • Проверьте план выполнения (используемые индексы, асимметрия данных и т. Д.)
  • выполнить этот запрос на сервере MS SQL - и измерить время выполнения
  • выполнить этот запрос на вашем клиентском компьютере по сети - и измерить время выполнения

После этого вы увидите, где вы больше всего теряете время...

Другие вопросы по тегам