【问题标题】:Inserting into MySQL from Python using mysql.connector module - How to use executemany() to inert rows and child rows?使用 mysql.connector 模块从 Python 插入 MySQL - 如何使用 executemany() 惰性行和子行?
【发布时间】:2021-06-16 22:18:50
【问题描述】:

我有一个在远程主机上运行的 MySQL 服务器。与主机的连接相当慢,它会影响我正在使用的 Python 代码的性能。我发现使用 executemany() 函数比使用循环插入许多行有了很大的改进。我的挑战是,对于我插入一个表的每一行,我需要在另一个表中插入几行。我下面的示例不包含太多数据,但我的生产数据可能是数千行。

我知道这个话题在很多地方都被问过很多次了,但是我没有看到任何明确的答案,所以我在这里问...

  • 有没有办法获取使用 executemany() 调用创建的自动生成密钥的列表?
  • 如果不是,我可以使用 last_insert_id() 并假设自动生成的键是按顺序排列的吗?
  • 看看下面的示例代码,有没有更简单或更好的方法来完成这项任务?
  • 如果我的 汽车 字典为空怎么办?不会插入任何行,那么 last_insert_id() 会返回什么?

我的桌子...

Table: makes
 pkey bigint autoincrement primary_key
 make varchar(255) not_null

Table: models
 pkey bigint autoincrement primary_key
 make_key bigint not null
 model varchar(255) not_null

...还有代码...

... 
cars = {"Ford": ["F150", "Fusion", "Taurus"],
        "Chevrolet": ["Malibu", "Camaro", "Vega"],
        "Chrysler": ["300", "200"], 
        "Toyota": ["Prius", "Corolla"]}

# Fill makes table with car makes
sql_data = list(cars.keys())
sql = "INSERT INTO makes (make) VALUES (%s)"
cursor.executemany(sql, sql_data)
rows_added = len(sqldata)

# Find the primary key for the first row that was just added
sql = "SELECT LAST_INSERT_ID()"
cursor.execute(sql)
rows = cursor.fetchall()
first_key = rows[0][0]

# Fill the models table with the car models, linked to their make
this_key = first_key
sql_data = []
for car in cars:
    for model in cars[car]:
        sql_data.append((this_key, car))
    
    this_key += 1

sql = "INSERT INTO models (make_key, model) VALUES (%s, %s)"
cursor.executemany(sql, sql_data)
    
cursor.execute("COMMIT")
...

【问题讨论】:

    标签: python mysql key executemany


    【解决方案1】:

    我不止一次地测量了批处理插入时大约 10 倍的加速。

    如果你在A表中插入1行,那么在B表中插入100行,不用担心1行的速度;担心100的速度。

    是的,获取插入生成的 id 很笨拙。我没有找到像LAST_INSERT_ID 这样直接的方法,但这仅适用于单行插入。

    因此,我开发了以下内容来执行一批“规范化”插入。这是您有一个将字符串映射到 ids 的表的地方(字符串可能会重复出现)。它需要两个步骤:首先是批量插入“新”字符串。然后获取所有需要的 id 并将它们复制到另一个表中。详细信息在此处列出:http://mysql.rjweb.org/doc.php/staging_table#normalization (抱歉,我不精通 python 或其他上百种与 MySQL 对话的方式,所以我不能给你 python 代码。)

    您的用例示例是“规范化”;我建议在主要交易之外进行。请注意,我的代码会处理多个连接,避免“燃烧”id 等。

    当您有子类别(“make”+“model”或“c​​ity”+“state”+“country”)时,我建议使用一个标准化表,而不是每个一个。

    在您的示例中,pkey 可以是 2 字节的 SMALLINT UNSIGNED(限制 64K),而不是庞大的 8 字节的 BIGINT

    【讨论】:

      猜你喜欢
      • 2014-04-09
      • 2014-05-03
      • 2013-08-17
      • 2020-04-01
      • 2019-10-25
      • 2016-08-21
      • 2014-05-23
      • 2015-07-14
      • 2019-05-05
      相关资源
      最近更新 更多