3

所以我一直在做一些研究,我需要编写一个INSERT语句来将唯一的客户端名称插入到我服务器上的一个表中。然而,数据库的默认标准已经有数千个客户端,当插入新客户端时,我们需要在尝试将其添加到系统之前检查它们是否已经存在。

我的问题是最好/最快的方法是什么?在客户表上运行一个简单的选择查询(按 ASC 排序),然后对结果进行二分搜索或其他操作,或者只执行类似于下面的 SQL 查询会更好吗?

IF NOT EXISTS (SELECT 1 FROM clients AS c WHERE c.clientname = ?)
BEGIN
  INSERT INTO clients (clientname, address, ...)
  VALUES (?, ?, ...)
END

这是一个缓慢的陈述吗?每次提交时,我可能必须运行数百次插入。

4

2 回答 2

3

如果您希望给定列是唯一的,则标准建议是创建一个 UNIQUE 约束。

ALTER TABLE clients ADD UNIQUE KEY (clientname);

然后尝试进行INSERT,如果没有匹配行会成功,如果有重复则会失败。不需要 SELECT。

于 2013-02-11T23:23:15.147 回答
2

在查询中根据磁盘操作计算 SQL 的成本并不少见(通常这意味着读/写一个块(通常 8 KB)是您的成本单位)。(在 Memory-DBs 中应该改变这种思路)。

如果您有成百上千个项目,并且每个项目......比如说 20 字节,那么您的完整数据库可能适合磁盘上的单个块(400 个项目/块)。也许它需要更多的街区,但万岁:这是一个可以忽略的小数字。使用这么小的数据库,您的数据库可能会在数据库的内存缓存中闲逛,您只需要为写访问付费。随着数据库的增长,如果您有索引,您需要的块访问数量可以成倍减少。

如果数据库中已经存在项目,则您的解决方案和 Bill 的解决方案都不会导致任何写入访问,因此它应该同样快。

有趣的部分是:

每次提交时,我可能必须运行数百次插入。

这意味着您可能会在磁盘上写入同一个块数百次。如果您可以一步完成,那会更快。但是,这确实是一个问题,因为我不知道任何允许这种行为的 SQL 函数。MySQL 的 INSERT 提供了一种在单个语句中指定多个值的方法。这可能是一个相当大的优势(我不知道 MySQL 如何处理这种情况),但它是 MySQL 特有的,并且不可移植。

另一种加快速度的方法是不要等到您更改的块被写入磁盘。这可能会在没有通知的情况下丢失数据,但可以显着提升性能。同样,这是特定于您使用的 DBMS。例如,如果您将 MySQL 与 InnoDB 一起使用,您可以innodb_flush_log_at_trx_commit=0在 my.ini 中设置选项来归档此行为。

最好在客户表上运行一个简单的选择查询(按 ASC 排序),然后对结果进行二进制搜索或其他操作

这会不必要地将大量数据从您的 DBMS 复制到客户端(可能位于不同的机器上,通过网络协议进行通信)。对于您的小型数据库,这仍然可以,但它不能很好地扩展。只有当它可以帮助您在单个操作中将数据保存到磁盘时,它才有用。

于 2013-02-11T23:55:07.107 回答