From 4932d67265d7bf61a8693fdc57336ee5e300dc27 Mon Sep 17 00:00:00 2001 From: Pierre Ducroquet Date: Thu, 28 Jul 2022 11:35:08 +0200 Subject: [PATCH] sql: change _fid idx on evolution table to contain id too This will improve several queries on tables where not that many different formdata, where sorting cost is (wrongly) considered worse than the cost offetching the whole table. --- wcs/sql.py | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/wcs/sql.py b/wcs/sql.py index 5ba8d68e4..75397daaa 100644 --- a/wcs/sql.py +++ b/wcs/sql.py @@ -979,21 +979,37 @@ def do_formdef_indexes(formdef, created, conn, cur, concurrently=False): existing_indexes = set() if not created: cur.execute( - '''SELECT indexname - FROM pg_indexes - WHERE schemaname = 'public' - AND tablename IN (%s, %s)''', + '''SELECT pci.relname, array_length(pi.indkey, 1) + FROM pg_index pi + JOIN pg_class pci on pci.oid = pi.indexrelid + JOIN pg_class pct on pct.oid = pi.indrelid + WHERE pci.relnamespace = 'public'::regnamespace + AND pct.relname in (%s, %s)''', (table_name, evolutions_table_name), ) - existing_indexes = {x[0] for x in cur.fetchall()} + existing_indexes = {x[0]: x[1] for x in cur.fetchall()} create_index = 'CREATE INDEX' if concurrently: create_index = 'CREATE INDEX CONCURRENTLY' - if evolutions_table_name + '_fid' not in existing_indexes: + fid_idx = evolutions_table_name + '_fid' + + if fid_idx in existing_indexes and existing_indexes[fid_idx] != 2: + # The index was previously (< #67757) on formdata_id only, so + # search for it with only one key and recreate it if needed. + if concurrently: + cur.execute('DROP INDEX CONCURRENTLY %s' % fid_idx) + else: + cur.execute('DROP INDEX %s' % fid_idx) cur.execute( - '''%s %s_fid ON %s (formdata_id)''' % (create_index, evolutions_table_name, evolutions_table_name) + '''%s %s_fid ON %s (formdata_id, id)''' + % (create_index, evolutions_table_name, evolutions_table_name) + ) + elif fid_idx not in existing_indexes: + cur.execute( + '''%s %s_fid ON %s (formdata_id, id)''' + % (create_index, evolutions_table_name, evolutions_table_name) ) for attr in ('receipt_time', 'anonymised', 'user_id', 'status'):