9
9
10
10
import argparse
11
11
import asyncio
12
- from concurrent import futures
13
12
import csv
14
13
import io
15
14
import itertools
16
15
import json
17
16
import re
18
17
import sys
19
18
import time
20
-
21
- import numpy as np
22
- import uvloop
19
+ from concurrent import futures
23
20
24
21
import aiopg
25
22
import asyncpg
23
+ import numpy as np
26
24
import postgresql
25
+ import psycopg
27
26
import psycopg2
28
27
import psycopg2 .extras
28
+ import uvloop
29
29
30
30
31
31
def _chunks (iterable , n ):
@@ -41,18 +41,26 @@ def _ctr(_):
41
41
42
42
43
43
def psycopg_connect (args ):
44
- conn = psycopg2 .connect (user = args .pguser , host = args .pghost ,
44
+ conn = psycopg .connect (user = args .pguser , host = args .pghost ,
45
45
port = args .pgport )
46
46
return conn
47
47
48
+ def psycopg2_connect (args ):
49
+ conn = psycopg2 .connect (user = args .pguser , host = args .pghost ,
50
+ port = args .pgport )
51
+ return conn
48
52
49
- def psycopg_execute (conn , query , args ):
53
+ def psycopg2_execute (conn , query , args ):
50
54
cur = conn .cursor (cursor_factory = psycopg2 .extras .DictCursor )
51
55
cur .execute (query , args )
52
56
return len (cur .fetchall ())
53
57
58
+ def psycopg_execute (conn , query , args ):
59
+ cur = conn .cursor (row_factory = psycopg .rows .dict_row )
60
+ cur .execute (query , args )
61
+ return len (cur .fetchall ())
54
62
55
- def psycopg_copy (conn , query , args ):
63
+ def psycopg2_copy (conn , query , args ):
56
64
rows , copy = args [:2 ]
57
65
f = io .StringIO ()
58
66
writer = csv .writer (f , delimiter = '\t ' )
@@ -64,6 +72,29 @@ def psycopg_copy(conn, query, args):
64
72
conn .commit ()
65
73
return cur .rowcount
66
74
75
+ def psycopg_copy (conn , query , args ):
76
+ rows , copy = args [:2 ]
77
+ f = io .StringIO ()
78
+ writer = csv .writer (f , delimiter = '\t ' )
79
+ for row in rows :
80
+ writer .writerow (row )
81
+ f .seek (0 )
82
+ with conn .cursor () as cur :
83
+ with cur .copy (query ) as copy :
84
+ copy .write (f .read ())
85
+ conn .commit ()
86
+ return cur .rowcount
87
+
88
+ def psycopg2_executemany (conn , query , args ):
89
+ cur = conn .cursor (cursor_factory = psycopg2 .extras .DictCursor )
90
+ cur .executemany (query , args )
91
+ return len (args )
92
+
93
+ def psycopg_executemany (conn , query , args ):
94
+ with conn .cursor () as cur :
95
+ cur .executemany (query , args )
96
+ return len (args )
97
+
67
98
68
99
def pypostgresql_connect (args ):
69
100
conn = postgresql .open (user = args .pguser , host = args .pghost ,
@@ -128,15 +159,33 @@ async def asyncpg_connect(args):
128
159
return conn
129
160
130
161
162
+ async def async_psycopg_connect (args ):
163
+ conn = await psycopg .AsyncConnection .connect (
164
+ user = args .pguser , host = args .pghost , port = args .pgport )
165
+ return conn
166
+
167
+
131
168
async def asyncpg_execute (conn , query , args ):
132
169
return len (await conn .fetch (query , * args ))
133
170
134
171
172
+ async def async_psycopg_execute (conn , query , args ):
173
+ cur = conn .cursor (row_factory = psycopg .rows .dict_row )
174
+ await cur .execute (query , args )
175
+ return len (await cur .fetchall ())
176
+
177
+
135
178
async def asyncpg_executemany (conn , query , args ):
136
179
await conn .executemany (query , args )
137
180
return len (args )
138
181
139
182
183
+ async def async_psycopg_executemany (conn , query , args ):
184
+ async with conn .cursor () as cur :
185
+ await cur .executemany (query , args )
186
+ return len (args )
187
+
188
+
140
189
async def asyncpg_copy (conn , query , args ):
141
190
rows , copy = args [:2 ]
142
191
result = await conn .copy_records_to_table (
@@ -145,6 +194,21 @@ async def asyncpg_copy(conn, query, args):
145
194
return int (count )
146
195
147
196
197
+ async def async_psycopg_copy (conn , query , args ):
198
+ rows , copy = args [:2 ]
199
+ f = io .StringIO ()
200
+ writer = csv .writer (f , delimiter = '\t ' )
201
+ for row in rows :
202
+ writer .writerow (row )
203
+ f .seek (0 )
204
+
205
+ async with conn .cursor () as cur :
206
+ async with cur .copy (query ) as copy :
207
+ await copy .write (f .read ())
208
+ await conn .commit ()
209
+ return cur .rowcount
210
+
211
+
148
212
async def worker (executor , eargs , start , duration , timeout ):
149
213
queries = 0
150
214
rows = 0
@@ -369,7 +433,15 @@ def die(msg):
369
433
help = 'PostgreSQL server user' )
370
434
parser .add_argument (
371
435
'driver' , help = 'driver implementation to use' ,
372
- choices = ['aiopg' , 'aiopg-tuples' , 'asyncpg' , 'psycopg' , 'postgresql' ])
436
+ choices = [
437
+ 'aiopg' ,
438
+ 'aiopg-tuples' ,
439
+ 'asyncpg' ,
440
+ 'psycopg2' ,
441
+ 'psycopg3' ,
442
+ 'psycopg3-async' ,
443
+ 'postgresql'
444
+ ],
373
445
parser .add_argument (
374
446
'queryfile' , help = 'file to read benchmark query information from' )
375
447
@@ -425,11 +497,25 @@ def die(msg):
425
497
asyncpg_connect , asyncpg_execute , asyncpg_copy , asyncpg_executemany
426
498
is_async = True
427
499
arg_format = 'native'
428
- elif args .driver == 'psycopg' :
429
- connector , executor , copy_executor = \
430
- psycopg_connect , psycopg_execute , psycopg_copy
500
+ elif args .driver == 'psycopg2' :
501
+ connector , executor , copy_executor , batch_executor = (
502
+ psycopg2_connect , psycopg2_execute ,
503
+ psycopg2_copy , psycopg2_executemany ,
504
+ )
505
+ is_async = False
506
+ arg_format = 'python'
507
+ elif args .driver == 'psycopg3' :
508
+ connector , executor , copy_executor , batch_executor = \
509
+ psycopg_connect , psycopg_execute , psycopg_copy , psycopg_executemany
431
510
is_async = False
432
511
arg_format = 'python'
512
+ elif args .driver == 'psycopg3-async' :
513
+ connector , executor , copy_executor , batch_executor = (
514
+ async_psycopg_connect , async_psycopg_execute ,
515
+ async_psycopg_copy , async_psycopg_executemany ,
516
+ )
517
+ is_async = True
518
+ arg_format = 'python'
433
519
elif args .driver == 'postgresql' :
434
520
connector , executor = pypostgresql_connect , pypostgresql_execute
435
521
is_async = False
0 commit comments