Оптимизация вставки MS SQL через pyodbc - PullRequest
0 голосов
/ 26 апреля 2019

Я получаю ответ JSON от вызова API и вставляю в базу данных MS SQL. Всего около 500 000 записей данных из API, которые я могу запросить 1000 одновременно.

Кажется, что оператор запроса вставки SQL занимает слишком много времени, и я предполагаю, что он может быть связан с конкатенацией запросов и преобразованием строк.

Столбцы SQL

self.query_headers = "([ac_serial_reg_key],[activity_date], 
    [aircraft_delivery_date],[activity_name],[activity_remark],
    [aircraft_category],[aircraft_financial_status],[aircraft_group],
    [aircraft_model],[aircraft_operational_status],[aircraft_registration_number], [aircraft_serial_number],
    [aircraft_type],[engine_model],[engine_type],[operator_name]
)"

Значения SQL затем объединяются путем итерации JSON-ответа

self.query_values = ''

for idx, set in enumerate(self.response.json()['results'], start=1):
    self.query_values += "("
    self.query_values += "'"+str(set['aircraft_registration_number'])+"_"+str(set['aircraft_serial_number'])+"',"
    self.query_values += self.validate_date(set['activity_date'])+","
    self.query_values += self.validate_date(set['aircraft_delivery_date'])+","
    self.query_values += "'"+str(set['activity_name'])+"',"
    self.query_values += "'"+str(set['activity_remark'])+"',"
    self.query_values += "'"+str(set['aircraft_category'])+"',"
    self.query_values += "'"+str(set['aircraft_financial_status'])+"',"
    self.query_values += "'"+str(set['aircraft_group'])+"',"
    self.query_values += "'"+str(set['aircraft_model'])+"',"
    self.query_values += "'"+str(set['aircraft_operational_status'])+"',"
    self.query_values += "'"+str(set['aircraft_registration_number'])+"',"
    self.query_values += "'"+str(set['aircraft_serial_number'])+"',"
    self.query_values += "'"+str(set['aircraft_type_lar'])+"',"
    self.query_values += "'"+str(set['engine_model'])+"',"
    self.query_values += "'"+str(set['engine_type'])+"',"
    self.query_values += "'"+str(set['operator_name'])+"'"
    self.query_values += ")"                    

if idx < self.response.json()['results_this_page']:
    self.query_values += ","

Как лучше всего разобрать возвращенные объекты JSON, чтобы создать один (или несколько) оператор вставки?

Вставить выписку

self.query = "INSERT INTO "+self.database+" "+self.query_headers+" VALUES"+self.query_values
self.cursor.execute(self.query)
self.cnxn.commit()

1 Ответ

3 голосов
/ 26 апреля 2019

По ссылке в моих комментариях что-то вроде этого может быстро вставить сотни тысяч значений json в таблицу:

JSON: 
N'[  
       { "id" : 2,"info": { "name": "John", "surname": "Smith" }, "age": 25 },  
       { "id" : 5,"info": { "name": "Jane", "surname": "Smith", "skills": ["SQL", "C#", "Azure"] }, "dob": "2005-11-04T12:00:00" }  
 ]'  

Вы бы параметризовали свой SQL-скрипт, чтобы ваше внешнее приложение заполняло @Переменная json (я не знаю, как это выглядит в python, извините, но это так же, как любой параметризованный sql).Вот сценарий

INSERT INTO Person(id, fn, ln, age, dob, skill)
SELECT *  
FROM 
  OPENJSON(@json)  
  WITH (id int 'strict $.id',  
        firstName nvarchar(50) '$.info.name', 
        lastName nvarchar(50) '$.info.surname',  
        age int, 
        dateOfBirth datetime2 '$.dob',
        skills nvarchar(max) '$.info.skills' as json) 
  OUTER APPLY 
    OPENJSON( skills ) --to "recurse" into the skills array
    WITH( skill nvarchar(8) '$' )

. Важно отметить, что при перезапуске данные о персонале для Джейн Смит будут повторяться один раз для каждого навыка:

5, Jane, Smith, ..., C#
5, Jane, Smith, ..., SQL
5, Jane, Smith, ..., Azure

Возможно, ваш json не знаетне имеет этой структуры.если это так, вы можете либо оставить его упакованным (не применять внешне), либо удалить ненужные вещи с помощью WHERE:

INSERT INTO Person(id, fn, ln, age, dob, skill)
SELECT *  
FROM 
  OPENJSON(@json)  
  WITH (
         ...
        skills nvarchar(max) '$.info.skills' as json) 
  OUTER APPLY 
    OPENJSON( skills ) --to "recurse" into the skills array
    WITH( skill nvarchar(8) '$' 
WHERE skill = 'C#'
...