I have a table with many fields, but the only important one here is meta which is a JSONB field (there is also a primary key, id, if needed). In this field, there is always a dict with key => value data, like this :
{
"card": "gold",
"country": "France",
"Type of travel": "Business",
"Company": "KLM"
}
I need to update this field to put every key in uppercase, like this :
{
"CARD": "gold",
"COUNTRY": "France",
"TYPE OF TRAVEL": "Business",
"COMPANY": "KLM"
}
The values, however, must keep their current cases - only the key are to be impacted.
I wrote a python script to do that, however it took multiple hours to update my testing set of 600k rows. The problem is that my production set is actually 2.5M rows and as long as the script is running I must stop the production, so I can't really have it running for days...
Is there any way to do this update in a full-sql way ? And would that be faster ?
I should add that there is no known list of possible keys in the field - the exact keys may (and do) vary from one rows to another, so I can't just say "here are the new keys", I need to retrieve them from them json object first.
Edit: The python script I tried to use is a Django management comment, so it use the ORM, but here it is :
print("Step 2: Verbatim...\t\t\tCounting...", end='\r')
verbatims = Verbatim.objects.all()
i = 0
total = len(verbatims)
to_save = []
for verbatim in verbatims:
verbatim.meta = up_dict(verbatim.meta)
to_save.append(verbatim)
i += 1
if i % 100 == 1:
print(f"Step 2: Verbatim...\t\t\t{i}/{total}", end='\r')
print("Step 2: Verbatim...\t\t\tSaving... ", end='\r')
Verbatim.objects.bulk_update(to_save, ['meta'], batch_size=10000)
print("Step 2: Verbatim...\t\t\t[OK] ")
It take around 5 secondes to go start the "counting" part, then around 2 seconds for the whole loop. Then the "saving" part was killed by the DB after 2 hours. Oh, and here is the up_dict function, if needed:
def up_dict(original):
return {
key.upper(): original[key] for key in original
}