使用具有一个条件的 WHERE 子句运行 100 个 SQL 查询,还是使用具有 100 个条件的 WHERE 子句的一个查询更好?

Posted

技术标签:

【中文标题】使用具有一个条件的 WHERE 子句运行 100 个 SQL 查询,还是使用具有 100 个条件的 WHERE 子句的一个查询更好?【英文标题】:Is it better to run 100 SQL queries with a WHERE clause that has one condition, or one query with a WHERE clause that has 100 conditions? 【发布时间】:2011-01-14 03:37:17 【问题描述】:

运行 100 个 SQL 查询是否更好?例如,如果我想查看一个表中是否已经存在 100 个用户名,是迭代 100 个查询还是执行一次查找 100 个用户名的复杂查询更好。

【问题讨论】:

【参考方案1】:

我没有做过任何测试,但我更喜欢一个大查询。对于 100 个查询,您必须连接到数据库、发送查询字符串并处理 100 次响应/结果。通过一个查询,您发送一个(更大的)查询,并得到一个响应。我不知道 100 次上下文切换的确切成本,但这可能不是微不足道的。无论如何,对于一个大型查询,数据库可能必须完成相同数量的工作。如果您检查的只是 1 个用户名与 100 个用户名,这不是一个非常复杂的查询,它更像是

select *
from users
where username in ('value1',...,'value100');

【讨论】:

切记避免SQL注入 谢谢。我不知道! 1 查询明显快于 100s(多个数量级),基于连接成本、SQL 编译、SQL 评估、文件分页、索引扫描、数据传输等。【参考方案2】:

查询越少越好。

【讨论】:

一般意义上的不正确。 100 个主键查找通常比在具有 100 万行的表上进行单个笛卡尔连接要快得多。一般而言,寻求更有效的查询,不一定是更少(但更有效的更少的查询是最好的)。 在其他条件相同的情况下,使用更少的查询会更好。但是不要忘记使用 EXPLAIN 检查任何大型查询,以确保它没有做一些你没想到的非常低效的事情。不过,在这个例子中,我想你只需要一个 WHERE username IN ... 无论如何。【参考方案3】:

少即是多。在这种情况下,执行最少的查询即可获得结果。

【讨论】:

【参考方案4】:

SQL 是基于设置的。最好使用具有 100 个条件的子句运行一个查询。请记住,每个查询代表一个单独的隐式事务 - 因此运行一百个简单查询而不是一个复杂查询(从处理和带宽的角度来看)需要更多开销。话虽如此,从实现的角度来看,无论性能如何,运行 100 个查询可能更容易。

【讨论】:

【参考方案5】:

恕我直言,这是个人喜好,除非您正在做一些跨越几张表等并处理大量数据的巨大疯狂的事情,否则无论哪种方式,速度提升都不会很大。

如果您确实决定通过查询来完成所有操作,请确保正确设置键和索引,否则对于每个查询,它必须读取整个表以找到所需的内容。

如果您设置好索引,您将获得巨大的速度提升。

【讨论】:

正确索引...我不久前就惨痛地吸取了教训!【参考方案6】:

如果你创建@table,并在@table中添加100个名字会更容易吗?

按 IN 语句过滤查询。

【讨论】:

【参考方案7】:

我敢打赌,一个大型查询会更快...

...但与其相信我的直觉,有一个简单的方法可以证明这一点。构建一个简单的性能原型并查看。

【讨论】:

【参考方案8】:

简短的回答是视情况而定。这取决于表中的数据、您运行的 where 子句的类型(主键与多键等)、结果集的大小等。在某些情况下,一个查询会快得多,在其他许多人会。

一般来说,执行的查询越少越好。然而话虽如此,100 个高效查询(例如主键查找)远好于 1 个非常低效的查询。

就您的具体问题而言,如果 100 个查询相同,则将它们合并为一个。如果它们是相关的(例如,为 100 个帖子获取作者),则将它们合并为一个。如果它们彼此无关,请不要将它们组合在一起(因为它会损害可读性和可维护性)。

【讨论】:

【参考方案9】:

这很快,但不是很漂亮:P

drop table if exists users;
create table users
(
user_id int unsigned not null auto_increment primary key,
username varbinary(32) unique not null
)
engine=innodb;

drop procedure if exists username_check;
delimiter #

create procedure username_check
(
in p_username_csv varchar(65535)
)
proc_main:begin

declare v_token varchar(255);
declare v_done tinyint unsigned default 0;
declare v_idx int unsigned default 1;

    if p_username_csv is null or length(p_username_csv) <= 0 then
        leave proc_main;
    end if;

    -- split the string into tokens and put into an in-memory table...

    create temporary table tmp(
      username varbinary(32),
      username_exists tinyint unsigned default 0,
     key (username)
    )engine = memory;   

    while not v_done do
     set v_token = trim(substring(p_username_csv, v_idx, 
      if(locate(',', p_username_csv, v_idx) > 0, 
        locate(',', p_username_csv, v_idx) - v_idx, length(p_username_csv))));

      if length(v_token) > 0 then
        set v_idx = v_idx + length(v_token) + 1;
        insert into tmp (username) values(v_token);
      else
        set v_done = 1;
      end if;
    end while;

   -- flag any that exist

    update tmp t inner join users u on t.username = u.username
      set t.username_exists = 1;

    select * from tmp order by username;

    drop temporary table if exists tmp;

end proc_main #

delimiter ;

select count(*) from users;
+----------+
| count(*) |
+----------+
|  1000000 |
+----------+
1 row in set (0.22 sec)


call username_check('user1,user2,user3... user250');

250 rows in set (0.01 sec)

【讨论】:

以上是关于使用具有一个条件的 WHERE 子句运行 100 个 SQL 查询,还是使用具有 100 个条件的 WHERE 子句的一个查询更好?的主要内容,如果未能解决你的问题,请参考以下文章

WHERE 子句中的 100 倍约束使查询极慢

sql语句中where后边的哪些条件会使索引失效 -- SQL语句优化

如何为 Amazon redshift 数据库编写查询,使相关查询的 where 子句具有两个条件?

如何使用 AREL 执行条件 where 子句

SQL Server If 条件在 where 子句?

使用具有一对多关系的 JPA 映射实体,如何添加连接条件