2017-06-01 53 views
0

我使用下面SQLAlchemy的代碼來從數據庫中性能SQLAlchemy的和或

q = session.query(hd_tbl).\ 
    join(dt_tbl, hd_tbl.c['data_type'] == dt_tbl.c['ID']).\ 
    filter(or_(and_(hd_tbl.c['object_id'] == get_id(row['object']), 
        hd_tbl.c['data_type'] == get_id(row['type']), 
        hd_tbl.c['data_provider'] == get_id(row['provider']), 
        hd_tbl.c['data_account'] == get_id(row['account'])) 
      for index, row in data.iterrows())).\ 
    with_entities(hd_tbl.c['ID'], hd_tbl.c['object_id'], 
        hd_tbl.c['data_type'], hd_tbl.c['data_provider'], 
        hd_tbl.c['data_account'], dt_tbl.c['value_type']) 

其中hd_tbldt_tbl在SQL數據庫兩個表,和data檢索某些數據通常是含有約1K-9K條目大熊貓數據幀。 hd_tbl目前包含大約90k行。

執行時間似乎隨着data的長度呈指數級增長。相應的sql語句(sqlalchemy)如下所示:

SELECT data_header.`ID`, data_header.object_id, data_header.data_type, data_header.data_provider, data_header.data_account, basedata_data_type.value_type 
FROM data_header INNER JOIN basedata_data_type ON data_header.data_type = basedata_data_type.`ID` 
WHERE data_header.object_id = %s AND data_header.data_type = %s AND data_header.data_provider = %s AND data_header.data_account = %s OR 
data_header.object_id = %s AND data_header.data_type = %s AND data_header.data_provider = %s AND data_header.data_account = %s OR 
... 
data_header.object_id = %s AND data_header.data_type = %s AND data_header.data_provider = %s AND data_header.data_account = %s OR 

表和列已完全索引,性能不令人滿意。目前將hd_tbldt_tbl的所有數據讀入內存並與熊貓合併功能合併會更快。但是,這似乎並不理想。任何人有關於如何改善sqlalchemy電話的想法?

編輯: 我能夠通過下列方式使用SQLAlchemy的tuple_ signifcantly提高性能:

header_tuples = [tuple([int(y) for y in tuple(x)]) for x in 
       data_as_int.values] 
q = session.query(hd_tbl). \ 
    join(dt_tbl, hd_tbl.c['data_type'] == dt_tbl.c['ID']). \ 
    filter(tuple_(hd_tbl.c['object_id'], hd_tbl.c['data_type'], 
        hd_tbl.c['data_provider'], 
        hd_tbl.c['data_account']).in_(header_tuples)). \ 
    with_entities(hd_tbl.c['ID'], hd_tbl.c['object_id'], 
        hd_tbl.c['data_type'], hd_tbl.c['data_provider'], 
        hd_tbl.c['data_account'], dt_tbl.c['value_type']) 

與相應的查詢......

SELECT data_header.`ID`, data_header.object_id, data_header.data_type, data_header.data_provider, data_header.data_account, basedata_data_type.value_type 
FROM data_header INNER JOIN basedata_data_type ON data_header.data_type = basedata_data_type.`ID` 
WHERE (data_header.object_id, data_header.data_type, data_header.data_provider, data_header.data_account) IN ((%(param_1)s, %(param_2)s, %(param_3)s, %(param_4)s), (%(param_5)s, ...)) 
+0

當然,它會變慢;你通過在其中一個表格上循環並構建一個具有數千條件的巨大'WHERE'子句來執行'JOIN'。你需要從你的數據框中創建一個臨時表,並做一個適當的'JOIN'。 – univerio

回答

1

我建議你創建一個字段上的複合索引object_id,data_type,data_provider,...具有相同的順序,將它們放置在表格中,並確保它們遵循相同的順序訂購您的WHERE條件。它可能會通過磁盤空間的成本加快您的請求速度。

此外,您可能會使用幾個隨後的小型SQL請求,而不是使用複雜的OR條件的大型查詢。在應用方積累提取的數據,或者如果數量足夠大,在快速臨時存儲(臨時表,noSQL等)中積累提取的數據。

另外,您可以檢查MySQL配置並增加與每個內存卷相關的值一個線程,請求等。一個好主意是檢查你的複合索引是否適合可用內存,否則它是無用的。

我猜數據庫調整可能有助於提高生產力。否則,您可能會分析您的應用程序的體系結構以獲得更重要的結果