如何避免将重复项插入数据库最有效的方法?

时间:2014-01-22 20:03:13

标签: python mysql database performance

我将首先描述我的情况,以便尽可能明确地提出以下问题。

为简单起见,假设我在MySQL数据库(InnoDB)中有一个表,其中包含有关结构的狗的记录,如下所示:

dog_id (PK) | dog_name

表中有10,000,000行(每个代表一个独特的狗)和dog_name列上的索引构建。

我的程序搜索我需要处理的兽医记录。每条记录都以某种方式与狗相连,每只狗有100条记录。我想找到尚未插入数据库的狗。

这意味着连续100次正在处理的记录可能是关于已经在数据库中的狗,因此狗不必添加到数据库中。但有时它会发生(如前1:100比例所述),我需要在数据库中添加一条狗,因为这是该程序第一次接近关于狗的记录。 (我希望这个例子能说明我的情况)

我的问题是: 什么是如何验证狗还没有插入数据库的最有效的方法呢?

  1. 将所有狗的名字(假设世界上所有的狗都有唯一的名字)加载到程序的存储器中(一组)并检查狗是否在该组中。当它在集合中时我跳过记录,当它不是我插入狗时。
  2. 将列定义为UNIQUE并尝试插入所有记录。当由于唯一性而导致数据库错误时,我只是跳过狗并继续。
  3. 查询数据库以确定每次处理记录时狗是否在数据库中,如果它在数据库中我跳过记录,如果不是,我将狗插入表中。
  4. 尽可能多地为您提供信息。我使用Python,SqlAlchemy,MySQL,InnoDB。

2 个答案:

答案 0 :(得分:1)

您应该使用dog_name作为主键,然后使用

INSERT INTO dogs (dog_name) VALUES ('[NAME HERE]') ON DUPLICATE KEY UPDATE dog_name='[NAME HERE]';

这只会插入唯一的狗名称。如果您仍想为每只狗使用数字ID,您可以将该列设置为自动增量,但主键应该是狗名称(假设所有都是唯一的)。

SQLAlchemy没有内置此功能,but can make force it to make a similar query with session.merge()

答案 1 :(得分:1)

选项2或选项3之类的东西效果最好;他们应该花费相似的时间,而获胜者将取决于MySQL / InnoDB究竟如何确定发生了冲突。我其实不知道;使用UNIQUE键插入可能会触发与SELECT相同的操作。原型和配置文件性能。

如果性能是一个问题,您可以随时手动编写SELECT语句,因为它相对简单。这减少了构建SQL的Python MySQL开销;这通常不是一个大问题,但SQLAlchemy可以添加几十层函数调用,支持它构造任意查询的能力。您可以使用Python字符串格式化来缩短这些调用。

假设's'是您的SQLAlchemy Session对象:

def dog_in_db(dog_name):
    q = 'SELECT COUNT (*) FROM dogs WHERE dog_name = %s;' % dog_name
    res = s.execute(q)
    return res.first()[0] > 0

您还可以尝试SELECTing并检查是否返回任何行:

    q 'SELECT dog_id FROM dogs WHERE dog_name = %s;' % dog_name
    res = s.execute(q)
    return res.rowcount() > 0

假设您的选项1意味着从数据库加载所有名称,它将会很慢。 MySQL将始终以比Python更快的速度执行它支持的任何单个操作;你在这里做的是完全相同的单一操作(在列表中找到一个成员)。