Оператор вставки PYODBC в MS Access DB очень медленный - PullRequest
0 голосов
/ 19 марта 2019

Я хочу ускорить мой оператор вставки в Access Db. данные составляют только 86500 записей и занимают более 24 часов. Часть кода, которую я ищу для ускорения, сравнивает две таблицы для дубликатов. Если дубликатов не найдено, вставьте эту строку. Я использую 64-битные Windows 10, 32-битный Python 2.7, 32-битный MS Access драйвер odbc и 32-битный модуль pyodbc. Любая помощь будет принята с благодарностью. Пример кода ниже.

def importDIDsACC():
    """Compare the Ledger to ImportDids to find any missing records"""
    imdidsLst = []
    ldgrLst = readMSAccess("ActivityNumber", "Ledger")
    for x in readMSAccess("DISP_NUM", "ImportDids"):
        if x not in ldgrLst and x not in imdidsLst:
            didsLst.append(x)
    #Select the records to import
    if len(imdidsLst) > 0:
        sql = ""
        for row in imdidsLst:
            sql += "DISP_NUM = '" + row[0]
            cursor.execute("SELECT * FROM ImportDids WHERE " + sql)
            rows = cursor.fetchall()
            #Import to Ledger
            dupChk = []
            for row in rows:
                if row[4] not in dupChk:
                    cursor.execute('INSERT into Ledger ([ActivityNumber], [WorkArea], [ClientName], [SurfacePurpose], [OpsApsDist], [AppDate], [LOADate], [EffDate], [AmnDate], [CanDate], [RenDate], [ExpDate], [ReiDate], [AmlDate], [DispType], [TRM], [Section], [Quarter], [Inspected_Date], [Inspection_Reason], [Inspected_By], [InspectionStatus], [REGION], [DOC], [STATCD]) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
                                   str(row[1]), str(row[18]), str(row[17]), row[14], str(row[26]), row[4], row[5], row[6], row[7], row[8], row[9], row[10], row[11], row[12], str(row[1][0:3]), trmCal(str(row[21]),str(row[20]), str(row[19])), str(row[22]), str(row[23]), inspSts(str(row[1]), 0),inspSts(str(row[1]), 1), inspSts(str(row[1]), 2), inspSts(str(row[1]), 3), str(row[27]), str(row[3]), str(row[13]))
                    dupChk.append(row[4])
            cnxn.commit()

def readMSAccess(columns, table):
    """Select all records from the chosen field"""
    sql = "SELECT "+ columns +  " FROM " + table
    cursor.execute(sql)
    rows = cursor.fetchall()
    return rows

def dbConn():
    """Connects to Access dataBase"""
    connStr = """
    DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};
    DBQ=""" + getDatabasepath() + ";"
    cnxn = pyodbc.connect(connStr)
    cursor = cnxn.cursor()
    return cursor, cnxn

def getDatabasepath():
    """get the path to the access database"""
    mycwd = os.getcwd()
    os.chdir("..")
    dataBasePath = os.getcwd() + os.sep + "LandsAccessTool.accdb"
    os.chdir(mycwd)
    return dataBasePath

# Connect to the Access Database
cursor, cnxn = dbConn()

# Update the Ledger with any new records from importDids
importDIDsACC()

1 Ответ

1 голос
/ 19 марта 2019

Не используйте внешний код для проверки на наличие дубликатов. Мощь базы данных (даже Access) максимизирует свои операции с наборами данных. Не пытайтесь переписать такой код, тем более что, как вы обнаружили, он неэффективен. Вместо этого импортируйте все во временную таблицу базы данных, а затем используйте Access (или соответствующий механизм данных Access) для выполнения операторов SQL для сравнения таблиц, либо находя, либо исключая повторяющиеся строки. Результаты этих запросов могут затем использоваться для создания и / или обновления других таблиц - все в контексте механизма базы данных. Конечно, настройте временную таблицу (таблицы) с соответствующими индексами и ключами, чтобы максимизировать эффективность.

В то же время обычно быстрее (можно ли сказать всегда?) При локальном сравнении наборов данных (например, таблиц) загружать все значения в некоторую коллекцию с возможностью поиска из одного запроса к базе данных (например, оператора SQL SELECT), затем используйте эту коллекцию в памяти для поиска совпадений. Это может показаться ироничным после моего последнего утверждения о максимизации возможностей базы данных, но большая идея заключается в понимании того, как обрабатывается набор данных в целом. Транспортировка данных туда и обратно между процессами Python и механизмом базы данных, даже если они находятся на одной машине, будет намного медленнее, чем обработка всего внутри процесса Python или всего процесса внутри механизма базы данных. Единственный случай, который может оказаться бесполезным, это когда удаленный набор данных слишком велик для загрузки, но 87 000 значений ключей определенно достаточно малы, чтобы загрузить все значения в коллекцию Python.

...