У нас есть приложение, построенное на Python, которое должно запускаться в разных базах данных, например SQLServer, MySQL и Postgres. Когда мы вставляем в SQL Server с помощью библиотеки pyodbc, это намного медленнее (20 раз!), Чем при выполнении тех же вставок в Postgres, используя psycopg2 или в MySQL, используя mysql.connector. У меня есть два вопроса: 1. В чем причина этой разницы в производительности? 2. Что мы можем сделать (помимо использования Postgres/MySQL)?
Когда MySQL Connector/Python встречает вызов executemany
для оператора INSERT, он создает один или несколько многострочных INSERT, тем самым уменьшая количество обращений к серверу. Например,
crsr = cnxn.cursor()
sql = "INSERT INTO mytable (id) VALUES (%s)"
params = [(x,) for x in range(3)]
crsr.executemany(sql, params)
отправляет на сервер MySQL один оператор INSERT
INSERT INTO mytable (id) VALUES (0),(1),(2)
Напротив, поведение по умолчанию для pyodbc заключается в отправке отдельных инструкций INSERT, поэтому
crsr = cnxn.cursor()
sql = "INSERT INTO mytable (id) VALUES (?)"
params = [(x,) for x in range(3)]
crsr.executemany(sql, params)
отправляет эквивалент
INSERT INTO mytable (id) VALUES (0)
INSERT INTO mytable (id) VALUES (1)
INSERT INTO mytable (id) VALUES (2)
требуя трех раундов на сервере вместо одного.
К счастью, текущие версии pyodbc поддерживают многострочные INSERT на SQL Server через свойство fast_executemany объекта Cursor, поэтому
crsr = cnxn.cursor()
sql = "INSERT INTO mytable (id) VALUES (?)"
params = [(x,) for x in range(3)]
crsr.fast_executemany = True
crsr.executemany(sql, params)
дает по существу тот же результат, что и пример MySQL Connector/Python выше.