MySQL:统一选择是否总是比单独的简单选择更快?

标签 mysql select stored-procedures query-performance

我有 3 个表:

# config - only 1 line in table
# Config (maxCount int) 
Create Table Config(maxCount int)  
# files- 20k lines in table
# Files(fileid int (pk), filename varchar (unique), revCount int) 
Create Table Files ( 
   fileid int(10) unsigned not null auto_increment,
   filename varchar(255) not null,
   revCount int(10) unsigned default 1,
   primary key(fileid),
   unique key filename(filename) 
);
# Revitions - 26k lines in table
# Revisions(revid (pk),  fileid int (fk), revname varchar,...) 
create table Revisions( 
   revid int(10) unsigned not null auto_increment,
   fileid int(10) unsigned not null, 
   revname varchar(255) not null,
   mtime  timestamp default CURRENT_TIMESTAMP,
   deleted boolean default false,
   primary key(revid),
   KEY fr_fileid_fk_idx (fileid),
   CONSTRAINT fr_fileid_fk FOREIGN KEY(fileid)
     REFERENCE Files(fileid)
     ON DELETE CASCADE ON UPDATE CASCADE 
);

并具有以下存储过程:

create procedure test1(in file_id int,out max_count int, out rev_count int, out last_revid int)
begin 
  select maxCount into max_count from Config limit 1;
  select revCount into rev_count from Files where fileid=file_id;
  select max(revid) into last_revid from Revitions where fileid=file_id;
end

我通过为文件 (20k) 中的每个文件 ID 调用它来检查 test1 的性能,调用运行大约需要 2.7 秒

测试过程是:

create procedure t1()
begin
  declare done int default 0;
  declare file_id,last_revid,max_count,rev_cout int default 0;
  declare c1 cursor for select fileid from files;
  declare continue handle for not found select 1 into done from (select 1) as t;
  open c1;
  read1: loop
    fetch c1 into file_id;
    if done=1 then
      leave read1;
    end if;
    call test1(file_id, max_count,rev_cout,last_revid);
  end loop;
  close c1;
end 

我尝试过其他解决方案,将 3 个选择统一为 1 个查询,如下所示:

create procedure test2(in file_id int,out max_count int, out rev_count int, out last_revid int)
begin 
  select maxCount, revCount, max(revid) 
  into   max_count,rev_count,last_revid 
  from Config, Files, Revitions 
  where Files.fileid=file_id AND Revitions.fileid=file_id
  limit 1;
end

我将 t1 更改为 t2,方法是将 call test1 更改为 call test2

结果是明显更好的性能,第二个 (t2) 花了大约 2 秒(效率提高了 25%!),我重复了很多次测试,结果总是一样的.

有什么原因吗?

我认为表的连接效率较低,然后分别从每个表中选择,但显然第二个更快。

那么我可以指望它并且总是更喜欢统一从多个表中选择的查询,还是应该检查每种情况哪个是最好的?

最佳答案

运行单个组合查询并不总是比运行三个单独的查询更快。有时是,有时不是。

问:[单个组合查询比三个单独查询更快]有什么原因吗?

答:从过程运行查询会产生开销,就像从任何客户端运行查询一样。存在从过程到数据库引擎的上下文切换,以及语句的数据库引擎开销......解析,语法检查,语义检查,确定访问计划,执行查询,具体化结果并将其返回给客户端,作为以及语句关闭时的清理。

我们可以使用一个组合语句来避免一些这种开销,一次往返数据库,而不是三个单独的往返语句执行。

但是并不能保证组合语句会更快。这实际上取决于语句的执行计划,以及执行每个查询需要多少时间。

如果单个组合查询的执行时间明显高于三个单独语句的总执行时间,这将有效抵消任何开销节省,并且整体上可能会更慢。


问:我可以指望它并且总是喜欢统一来自多个表的选择查询,还是应该检查每种情况哪个是最好的?

A:通常组合查询会更快。但在一般情况下,我们不能“指望”它。我们需要检查每个案例。

关于MySQL:统一选择是否总是比单独的简单选择更快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48154403/

相关文章:

c# - 我可以将 DBNull 传递给 Integer 类型变量吗?

python - 为什么我们要在sqlalchemy中设置local_infile=1来加载本地文件? sqlalchemy 中不允许加载文件的问题

php - 编写查询以特定方式获取数据

javascript - 动态表ajax替换页面中所有行/表单中的元素

javascript - 使用 jQuery 在选择列表上进行验证

html - 点击标签打不开选择

MYSQL select查询,同一列必须存在多个条件

php - SQL 查询中的 While 循环

java - 如何使用java运行mysql存储过程

stored-procedures - 我可以检查唯一性并在 Cosmos DB 存储过程中写入文档吗