2016-06-20 113 views
1

問題

我正在嘗試使用python,特別是SQLalchemy,pymssql和pandas.read_sql讀取MS SQL Server中的表。我想執行查詢,把結果放到一個熊貓數據框中,並以合理的速度繼續我的一天,但一個相當簡單的查詢(輸出= 100 MB)在局域網連接上花費了將近5-10分鐘,使用以太網電纜 - 看不到無線網絡。是SQLalchemy - pymssql - 熊貓總是很慢,還是我做錯了?

帶有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 MB的423秒是約230 KB/s,這我想通過以太網連接僅僅是痛苦的緩慢。瓶頸必須是在SQL Server本身


查詢信息

SQL服務器本身就是一個Wonderware公司成立,這可能會或可能不會有什麼用它做。在下面的查詢中,我要求在1個月的時間範圍內分辨率爲5000毫秒或5秒的6個不同標籤的值。

以下是查詢本身的樣子:

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:[email protected]' 
    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 

問題

這是怎麼回事?這是我使用的軟件包中的一個限制,還是我可以用我所擁有的軟件加快速度?

This question似乎與OP試圖寫入到SQL Server的事實有關。它表示使用'BULK INSERT'而不是通過使用.csv文件的熊貓更快,但這不是從sql server讀取的可行選項。我應該有一個包含所有日期/時間和所有標籤的.csv文件的目錄!?這將首先否定sql服務器的使用,不是嗎?

+0

你還可以發佈爲「Runtime.dbo.AnalogHistory」表定義了哪些索引以及此查詢的執行計劃嗎? – MaxU

+0

我不知道該怎麼做,這是一個選項,我給查詢或通過MS管理工作室確定? – cbcoutinho

+1

請檢查SO或詢問Google如何查找索引和執行計劃。除此之外,你還想知道這個表中總共有多少行,它有多大......你只需要一個月的時間就可以獲得高達3.2M的行,一個'wwResolution'和6個標籤,所以你的表可能會包含更多內容,如果您的select語句將執行FTS(全表掃描) - 這意味着MS SQL必須先讀取整個表格,應用過濾器並將數據返回給客戶端。您可以在查詢執行計劃中看到。 – MaxU

回答

2

我想你打電話給你的executeQuery()函數循環 - 很多次,每次你重新創建一個SQLAlchemy引擎,這會讓它變慢。

因此,嘗試一次創建你的數據庫連接,並用它多次:

import pandas as pd 
import pymssql 
import sqlalchemy 

connection_string = 'mssql+pymssql://user:[email protected]' 
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如果在MS SQL側的DateTime列是DateTime數據類型的,SQLAlchemy的應該將其映射到Python datetime類型。所以最終它應該已經是np.datetime64 ...

如果您曾經或非常調用它幾次,然後我會做到以下幾點:

  • 檢查執行計劃(使用的索引,數據偏等等)
  • 執行MS SQL服務器上的這個查詢 - 和測量的執行時間
  • 通過網絡在客戶機上執行這個查詢 - 和測量的執行時間

後,你會看到你在哪裏最多可以放鬆時間...

+0

將連接語句帶出函數是有道理的;然而,這似乎並沒有改善我身邊的事情。其次,我還沒有能夠獲得'parse_dates'選項 – cbcoutinho

相關問題