I need to insert multiple rows with one query (number of rows is not constant), so I need to execute query like this one:
INSERT INTO t (a, b) VALUES (1, 2), (3, 4), (5, 6);
The only way I know is
args = [(1,2), (3,4), (5,6)]
args_str = ','.join(cursor.mogrify("%s", (x, )) for x in args)
cursor.execute("INSERT INTO t (a, b) VALUES "+args_str)
but I want some simpler way.
Update with psycopg2 2.7:
The classic
executemany()
is about 60 times slower than @ant32 's implementation (called "folded") as explained in this thread: https://www.postgresql.org/message-id/20170130215151.GA7081%40deb76.aryehleib.comThis implementation was added to psycopg2 in version 2.7 and is called
execute_values()
:Previous Answer:
To insert multiple rows, using the multirow
VALUES
syntax withexecute()
is about 10x faster than using psycopg2executemany()
. Indeed,executemany()
just runs many individualINSERT
statements.@ant32 's code works perfectly in Python 2. But in Python 3,
cursor.mogrify()
returns bytes,cursor.execute()
takes either bytes or strings, and','.join()
expectsstr
instance.So in Python 3 you may need to modify @ant32 's code, by adding
.decode('utf-8')
:Or by using bytes (with
b''
orb""
) only:I built a program that inserts multiple lines to a server that was located in another city.
I found out that using this method was about 10 times faster than
executemany
. In my casetup
is a tuple containing about 2000 rows. It took about 10 seconds when using this method:and 2 minutes when using this method:
Finally in SQLalchemy1.2 version, this new implementation is added to use psycopg2.extras.execute_batch() instead of executemany when you initialize your engine with use_batch_mode=True like:
http://docs.sqlalchemy.org/en/latest/changelog/migration_12.html#change-4109
Then someone would have to use SQLalchmey won't bother to try different combinations of sqla and psycopg2 and direct SQL together..
All of these techniques are called 'Extended Inserts" in Postgres terminology, and as of the 24th of November 2016, it's still a ton faster than psychopg2's executemany() and all the other methods listed in this thread (which i tried before coming to this answer).
Here's some code which doesnt use cur.mogrify and is nice and simply to get your head around:
But it should be noted that if you can use copy_from(), you should use copy_from ;)
Nicely execute in batches using record template with psycopg2 !
If you want UPSERT (Insert+Update) as well in postgres with batches: postgres_utilities
Using aiopg - The snippet below works perfectly fine