簡體   English   中英

提高Python Cx_Oracle中的SQL查詢性能

[英]Improve performance SQL query in Python Cx_Oracle

我實際上使用Python中的Cx_Oracle庫與我的數據庫Oracle一起工作。

import cx_Oracle as Cx

# Parameters for server connexion
dsn_tns = Cx.makedsn(_ip, _port, service_name=_service_name)

# Connexion with Oracle Database
db = Cx.connect(_user, _password, dsn_tns)

# Obtain a cursor for make SQL query
cursor = db.cursor()

在某些情況下,我的查詢之一將Python數據幀的INSERT寫入我的Oracle目標表。

query = INSERT INTO ORA_TABLE(ID1, ID2) 
SELECT :1, :2
FROM DUAL 
WHERE (:1 != 'NF' AND :1 NOT IN (SELECT ID1 FROM ORA_TABLE)) 
   OR (:1 = 'NF' AND :2 NOT IN (SELECT ID2 FROM ORA_TABLE))

該查詢的目標是僅將符合條件的行寫入WHERE。

實際上,當我的Oracle目標表中的行很少時,此查詢會很好地工作。 但是,如果我的目標Oracle表具有超過100 000行,那將非常慢,因為我在WHERE條件下通讀了所有表。

有沒有一種方法可以通過join或其他方式提高此查詢的性能?

代碼結尾:

# SQL query incoming
cursor.prepare(query)

# Launch query with Python dataset
cursor.executemany(None, _py_table.values.tolist())

# Commit changes into Oracle database
db.commit()

# Close the cursor
cursor.close()

# Close the server connexion
db.close()

這是一個可能有幫助的解決方案:您具有的SQL條件為OR,並且對於給定值,該條件中只有一部分為真。 因此,我將通過檢查代碼中的以下內容並將其構造為兩個插入而不是一個插入而將其分為兩部分,並且在任何時間點都只會執行一個: IF:1!='NF'然后使用以下插入:

 INSERT INTO ORA_TABLE (ID1, ID2)
   SELECT :1, :2
     FROM DUAL
    WHERE (:1 NOT IN (SELECT ID1
                        FROM ORA_TABLE));

和IF:1 ='NF'然后使用以下插入:

INSERT INTO ORA_TABLE (ID1, ID2)
   SELECT :1, :2
     FROM DUAL
    WHERE (:2 NOT IN (SELECT ID2
                        FROM ORA_TABLE));

因此,您在代碼中檢入:1的值是什么,並根據情況使用兩個簡化的插入。 請檢查此功能是否與原始查詢相同,並驗證它是否可以縮短響應時間。

假設是熊貓,請考慮將數據導出為表以用作最終遷移的階段,在此遷移中,子查詢僅運行一次,而不是對數據集的每一行都運行一次 在熊貓,你需要與接口的SQLAlchemy運行to_sql導出操作。 注意:這假定您的連接用戶具有DROP TABLECREATE TABLE特權。

另外,考慮使用EXISTS子查詢來組合兩個IN子查詢。 下面的子查詢嘗試與您的邏輯相反進行排除。

import sqlalchemy

...
engine = sqlalchemy.create_engine("oracle+cx_oracle://user:password@dsn")

# EXPORT DATA -ALWAYS REPLACING
pandas_df.to_sql('myTempTable', con=engine, if_exists='replace')

# RUN TRANSACTION
with engine.begin() as cn:
   sql = """INSERT INTO ORA_TABLE (ID1, ID2)
            SELECT t.ID1, t.ID2
            FROM myTempTable t
            WHERE EXISTS 
                (
                  SELECT 1 FROM ORA_TABLE sub
                  WHERE (t.ID1 != 'NF' AND t.ID1 = sub.ID1)
                     OR (t.ID1  = 'NF' AND t.ID2 = sub.ID2) 
                )
         """
   cn.execute(sql)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM