所以我一直在做一些研究,我需要编写一个INSERT
语句,将唯一的客户端名称插入到我服务器上的表中。但是,数据库的默认标准已经包含数千个客户端,并且在插入新客户端时,我们需要在尝试将其添加到系统之前检查它们是否已存在。
我的问题是最好/最快的方法是什么?在客户端表上运行一个简单的选择查询(由ASC排序),并对结果执行二进制搜索或其他操作会更好吗,或者只是执行类似于下面的SQL查询?
IF NOT EXISTS (SELECT 1 FROM clients AS c WHERE c.clientname = ?)
BEGIN
INSERT INTO clients (clientname, address, ...)
VALUES (?, ?, ...)
END
这是一个缓慢的陈述吗?我可能每次提交都要运行插件几百次。
答案 0 :(得分:3)
如果您希望给定列是唯一的,则标准建议是创建UNIQUE约束。
ALTER TABLE clients ADD UNIQUE KEY (clientname);
然后尝试执行INSERT,如果没有匹配的行,它将成功,如果有重复,它将失败。不需要选择。
答案 1 :(得分:2)
在磁盘操作方面计算查询中SQL的成本并不常见(通常这意味着读取/写入块(通常为8 KB)是您的成本单位)。 (在Memory-DB中应该改变一些关于这种思路的方法)。
如果您有数百个,可能有数千个项目,并且每个项目都是...说20个字节,那么您的完整数据库可能适合磁盘上的单个块(400个项目/块)。也许它需要更多的块,但欢呼:这是一个可忽略的小数字。使用如此小的数据库,您的数据库可能会在数据库的内存缓存中休息,您只需要支付写访问权。 随着数据库的增长,如果您有索引,则所需的块访问次数可以指数级地减少。
如果某个项目已存在于数据库中,那么您的解决方案和Bill的解决方案都不会导致任何写入权限,因此它们应该同样快速。
有趣的部分是:
我可能必须每次运行插件数百次 提交。
这意味着您可能会在磁盘上写一个相同的块数百次。如果你只需一步就能做到这一点会更快。但是,这确实是一个问题,因为我不知道任何允许此行为的SQL函数。 MySQL的INSERT提供了一种在单个语句中指定多个值的方法。这个 MIGHT 是一个相当大的优点(我不知道MySQL如何处理这种情况)但它是特定于MySQL而且不可移植。
另一种加快速度的方法是不要等到你更改的块写入磁盘。这可能会在没有通知的情况下丢失数据,但可能会显着提升性能。这也是您使用的DBMS特有的。例如。如果你将MySQL与InnoDB一起使用,你可以在你的my.ini中设置选项innodb_flush_log_at_trx_commit=0
来实现这种行为。
在clients表上运行简单的select查询会更好吗? (由ASC命令),并对结果进行二元搜索或其他内容
这将不必要地将大量数据从您的DBMS复制到客户端(可能在不同的机器上,通过网络协议进行通信)。这对于您的小型数据库仍然可以,但它不能很好地扩展。它可能只有在帮助您将单个操作中的数据保存到磁盘时才有用。