@@ -30,11 +30,6 @@ def execute(self, n_runs, params: dict):
30
30
experiment = params ['name' ]
31
31
tqdm .write (f'` Perform experiment { suite } /{ benchmark } /{ experiment } with configuration PostgreSQL.' )
32
32
33
- try :
34
- self .clean_up ()
35
- except psycopg2 .OperationalError as ex :
36
- raise ConnectorException (str (ex ))
37
-
38
33
# map that is returned with the measured times
39
34
measurement_times = dict ()
40
35
@@ -47,21 +42,24 @@ def execute(self, n_runs, params: dict):
47
42
48
43
verbose_printed = False
49
44
for _ in range (n_runs ):
45
+ # Set up database
46
+ self .setup ()
47
+
48
+ # Connect to database and set up tables
49
+ connection = psycopg2 .connect (** db_options )
50
50
try :
51
- # Set up database
52
- self .setup ()
53
- connection = psycopg2 .connect (** db_options )
54
51
connection .autocommit = True
55
52
cursor = connection .cursor ()
56
53
cursor .execute ("set jit=off;" )
57
54
self .create_tables (cursor , params ['data' ], with_scale_factors )
55
+ finally :
58
56
connection .close ()
59
57
60
-
61
- # If tables contain scale factors, they have to be loaded separately for every case
62
- if ( with_scale_factors or not bool ( params . get ( 'readonly' )) ):
63
- for case , query_stmt in params [ 'cases' ]. items ():
64
- connection = psycopg2 . connect ( ** db_options )
58
+ # If tables contain scale factors, they have to be loaded separately for every case
59
+ if ( with_scale_factors or not bool ( params . get ( 'readonly' ))):
60
+ for case , query_stmt in params [ 'cases' ]. items ( ):
61
+ connection = psycopg2 . connect ( ** db_options )
62
+ try :
65
63
connection .autocommit = True
66
64
cursor = connection .cursor ()
67
65
# Create tables from tmp tables with scale factor
@@ -74,49 +72,18 @@ def execute(self, n_runs, params: dict):
74
72
num_rows = round ((table ['lines_in_file' ] - header ) * sf )
75
73
cursor .execute (f"DELETE FROM { table_name } ;" ) # empty existing table
76
74
cursor .execute (f"INSERT INTO { table_name } SELECT * FROM { table_name } _tmp LIMIT { num_rows } ;" ) # copy data with scale factor
75
+ finally :
77
76
connection .close ()
78
77
79
- # Write case/query to a file that will be passed to the command to execute
80
- with open (TMP_SQL_FILE , "w" ) as tmp :
81
- tmp .write ("\\ timing on\n " )
82
- tmp .write (query_stmt + '\n ' )
83
- tmp .write ("\\ timing off\n " )
84
-
85
- # Execute query as benchmark and get measurement time
86
- command = f"psql -U { db_options ['user' ]} -d { db_options ['dbname' ]} -f { TMP_SQL_FILE } | grep 'Time' | cut -d ' ' -f 2"
87
- if self .verbose :
88
- tqdm .write (f" $ { command } " )
89
- if not verbose_printed :
90
- verbose_printed = True
91
- with open (TMP_SQL_FILE ) as tmp :
92
- tqdm .write (" " + " " .join (tmp .readlines ()))
93
-
94
- timeout = TIMEOUT_PER_CASE
95
- benchmark_info = f"{ suite } /{ benchmark } /{ experiment } [PostgreSQL]"
96
- try :
97
- durations = self .run_command (command , timeout , benchmark_info )
98
- except ExperimentTimeoutExpired as ex :
99
- if case not in measurement_times .keys ():
100
- measurement_times [case ] = list ()
101
- measurement_times [case ].append (TIMEOUT_PER_CASE * 1000 )
102
- else :
103
- for idx , line in enumerate (durations ):
104
- time = float (line .replace ("\n " , "" ).replace ("," , "." )) # in milliseconds
105
- if case not in measurement_times .keys ():
106
- measurement_times [case ] = list ()
107
- measurement_times [case ].append (time )
108
-
109
-
110
- # Otherwise, tables have to be created just once before the measurements (done above)
111
- else :
112
- # Write cases/queries to a file that will be passed to the command to execute
78
+ # Write case/query to a file that will be passed to the command to execute
113
79
with open (TMP_SQL_FILE , "w" ) as tmp :
80
+ tmp .write (f'set statement_timeout = { TIMEOUT_PER_CASE * 1000 :.0f} ;\n ' )
114
81
tmp .write ("\\ timing on\n " )
115
- for case_query in params ['cases' ].values ():
116
- tmp .write (case_query + '\n ' )
82
+ tmp .write (query_stmt + '\n ' )
117
83
tmp .write ("\\ timing off\n " )
84
+ tmp .write (f'set statement_timeout = 0;\n ' )
118
85
119
- # Execute query file and collect measurement data
86
+ # Execute query as benchmark and get measurement time
120
87
command = f"psql -U { db_options ['user' ]} -d { db_options ['dbname' ]} -f { TMP_SQL_FILE } | grep 'Time' | cut -d ' ' -f 2"
121
88
if self .verbose :
122
89
tqdm .write (f" $ { command } " )
@@ -125,27 +92,59 @@ def execute(self, n_runs, params: dict):
125
92
with open (TMP_SQL_FILE ) as tmp :
126
93
tqdm .write (" " + " " .join (tmp .readlines ()))
127
94
128
- timeout = DEFAULT_TIMEOUT + TIMEOUT_PER_CASE * len ( params [ 'cases' ])
95
+ timeout = TIMEOUT_PER_CASE
129
96
benchmark_info = f"{ suite } /{ benchmark } /{ experiment } [PostgreSQL]"
130
97
try :
131
98
durations = self .run_command (command , timeout , benchmark_info )
132
99
except ExperimentTimeoutExpired as ex :
133
- for case in params ['cases' ].keys ():
134
- if case not in measurement_times .keys ():
135
- measurement_times [case ] = list ()
136
- measurement_times [case ].append (TIMEOUT_PER_CASE * 1000 )
100
+ if case not in measurement_times .keys ():
101
+ measurement_times [case ] = list ()
102
+ measurement_times [case ].append (TIMEOUT_PER_CASE * 1000 )
137
103
else :
138
104
for idx , line in enumerate (durations ):
139
105
time = float (line .replace ("\n " , "" ).replace ("," , "." )) # in milliseconds
140
- case = list (params ['cases' ].keys ())[idx ]
141
106
if case not in measurement_times .keys ():
142
107
measurement_times [case ] = list ()
143
108
measurement_times [case ].append (time )
144
109
145
- finally :
146
- if (connection ):
147
- connection .close ()
148
- self .clean_up ()
110
+ # Otherwise, tables have to be created just once before the measurements (done above)
111
+ else :
112
+ # Write cases/queries to a file that will be passed to the command to execute
113
+ with open (TMP_SQL_FILE , "w" ) as tmp :
114
+ tmp .write (f'set statement_timeout = { TIMEOUT_PER_CASE * 1000 :.0f} ;\n ' )
115
+ tmp .write ("\\ timing on\n " )
116
+ for case_query in params ['cases' ].values ():
117
+ tmp .write (case_query + '\n ' )
118
+ tmp .write ("\\ timing off\n " )
119
+ tmp .write (f'set statement_timeout = 0;\n ' )
120
+
121
+ # Execute query file and collect measurement data
122
+ command = f"psql -U { db_options ['user' ]} -d { db_options ['dbname' ]} -f { TMP_SQL_FILE } | grep 'Time' | cut -d ' ' -f 2"
123
+ if self .verbose :
124
+ tqdm .write (f" $ { command } " )
125
+ if not verbose_printed :
126
+ verbose_printed = True
127
+ with open (TMP_SQL_FILE ) as tmp :
128
+ tqdm .write (" " + " " .join (tmp .readlines ()))
129
+
130
+ timeout = DEFAULT_TIMEOUT + TIMEOUT_PER_CASE * len (params ['cases' ])
131
+ benchmark_info = f"{ suite } /{ benchmark } /{ experiment } [PostgreSQL]"
132
+ try :
133
+ durations = self .run_command (command , timeout , benchmark_info )
134
+ except ExperimentTimeoutExpired as ex :
135
+ for case in params ['cases' ].keys ():
136
+ if case not in measurement_times .keys ():
137
+ measurement_times [case ] = list ()
138
+ measurement_times [case ].append (TIMEOUT_PER_CASE * 1000 )
139
+ else :
140
+ for idx , line in enumerate (durations ):
141
+ time = float (line .replace ("\n " , "" ).replace ("," , "." )) # in milliseconds
142
+ case = list (params ['cases' ].keys ())[idx ]
143
+ if case not in measurement_times .keys ():
144
+ measurement_times [case ] = list ()
145
+ measurement_times [case ].append (time )
146
+
147
+ self .clean_up ()
149
148
150
149
return {'PostgreSQL' : measurement_times }
151
150
@@ -154,25 +153,26 @@ def execute(self, n_runs, params: dict):
154
153
def setup (self ):
155
154
# Delete existing 'benchmark_tmp' database and create a new empty one
156
155
connection = psycopg2 .connect (user = db_options ['user' ])
157
- connection .autocommit = True
158
- cursor = connection .cursor ()
159
- cursor .execute (f"DROP DATABASE IF EXISTS { db_options ['dbname' ]} ;" )
160
- cursor .execute (f"CREATE DATABASE { db_options ['dbname' ]} ;" )
161
- connection .close ()
156
+ try :
157
+ connection .autocommit = True
158
+ cursor = connection .cursor ()
159
+ cursor .execute (f"DROP DATABASE IF EXISTS { db_options ['dbname' ]} ;" )
160
+ cursor .execute (f"CREATE DATABASE { db_options ['dbname' ]} ;" )
161
+ finally :
162
+ connection .close ()
162
163
163
164
164
165
# Deletes the used temporary database and file
165
166
def clean_up (self ):
166
167
connection = psycopg2 .connect (user = db_options ['user' ])
167
- connection .autocommit = True
168
- cursor = connection .cursor ()
169
168
try :
169
+ connection .autocommit = True
170
+ cursor = connection .cursor ()
170
171
cursor .execute (f"DROP DATABASE IF EXISTS { db_options ['dbname' ]} ;" )
171
- except Exception as ex :
172
- tqdm .write (f"Unexpeced error while executing 'DROP DATABASE IF EXISTS { db_options ['dbname' ]} ' : { ex } " )
173
- connection .close ()
174
- if os .path .exists (TMP_SQL_FILE ):
175
- os .remove (TMP_SQL_FILE )
172
+ finally :
173
+ connection .close ()
174
+ if os .path .exists (TMP_SQL_FILE ):
175
+ os .remove (TMP_SQL_FILE )
176
176
177
177
178
178
# Parse attributes of one table, return as string ready for a CREATE TABLE query
@@ -245,7 +245,6 @@ def run_command(self, command, timeout, benchmark_info):
245
245
out , err = process .communicate ("" .encode ('latin-1' ), timeout = timeout )
246
246
except subprocess .TimeoutExpired :
247
247
process .kill ()
248
- self .clean_up ()
249
248
raise ExperimentTimeoutExpired (f'Query timed out after { timeout } seconds' )
250
249
finally :
251
250
if process .poll () is None : # if process is still alive
0 commit comments