我将首先描述我的情况,以便尽可能明确地提出以下问题。
为简单起见,假设我在MySQL数据库(InnoDB)中有一个表,其中包含有关结构的狗的记录,如下所示:
dog_id (PK) | dog_name
表中有10,000,000行(每个代表一个独特的狗)和dog_name列上的索引构建。
我的程序搜索我需要处理的兽医记录。每条记录都以某种方式与狗相连,每只狗有100条记录。我想找到尚未插入数据库的狗。
这意味着连续100次正在处理的记录可能是关于已经在数据库中的狗,因此狗不必添加到数据库中。但有时它会发生(如前1:100比例所述),我需要在数据库中添加一条狗,因为这是该程序第一次接近关于狗的记录。 (我希望这个例子能说明我的情况)
我的问题是: 什么是如何验证狗还没有插入数据库的最有效的方法呢?
尽可能多地为您提供信息。我使用Python,SqlAlchemy,MySQL,InnoDB。
答案 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更快的速度执行它支持的任何单个操作;你在这里做的是完全相同的单一操作(在列表中找到一个成员)。