使用具有一个条件的 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 子句的一个查询更好?的主要内容,如果未能解决你的问题,请参考以下文章
sql语句中where后边的哪些条件会使索引失效 -- SQL语句优化