mysql:统一选择总是比单独的简单选择快吗?

8zzbczxx  于 2021-06-21  发布在  Mysql
关注(0)|答案(2)|浏览(341)

我有三张table:


# 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

我通过为文件中的每个fileid(20k)调用test1来检查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

我改变了 t1t2 通过改变 call test1call test2 结果是一个明显更好的表现,第二( t2 )大约花了2秒钟(效率提高了25%!),我重复了很多次测试结果总是一样的。
有什么原因吗?为什么?
我认为表的连接比单独从每个表中选择效率低,但显然第二个更快。
因此,我可以指望它,总是喜欢统一从几个表中选择查询,还是应该检查每个情况哪一个是最好的?

6gpjuf90

6gpjuf901#

只要你在比较技巧,就试试这个:

SELECT
  ( select maxCount FROM Config limit 1 ) AS max_count,
  ( select revCount FROM Files where fileid=file_id ) AS rev_count,
  ( select max(revid) FROM Revitions where fileid=file_id ) AS last_revid ;

(不需要存储过程。)

brc7rcf0

brc7rcf02#

运行单个组合查询并不总是比运行三个单独的查询快。有时是,有时不是。
问:为什么[一个组合查询比三个单独查询快]?
答:从过程运行查询会有开销,就像从任何客户机运行查询一样。有一个从过程到数据库引擎的上下文切换,以及语句的数据库引擎开销。。。解析、语法检查、语义检查、确定访问计划、执行查询、将结果具体化并返回给客户机,以及关闭语句时的清理。
我们可以使用一个组合语句(一个到数据库的往返语句)来代替三个单独的往返语句执行,从而避免一些开销。
但不能保证合并声明会更快。这实际上取决于语句的执行计划,以及执行每个查询所需的时间。
如果单个组合查询的执行时间明显高于三个单独语句的总执行时间,则这将有效地抵消任何开销节省,并且总体上可能会更慢。
问:我可以指望它,总是喜欢统一从几个表中选择查询,还是应该检查每个情况哪一个是最好的?
答:通常情况下,组合查询会更快。但在一般情况下,我们不能“指望”它。我们需要检查每个案子。

相关问题