Mysql:如何在表A中找到内存表中不在表B中的所有项

时间:2010-10-14 10:40:51

标签: mysql

我有临时内存表A和B.每个包含1列整数值 我需要找到A中但不在B中的所有值。

问题在于它非常慢,因为(我认为)内存表使用哈希而不是有序键。

如何有效地执行它?目前我正在使用 SELECT val FROM tableA WHERE val NOT IN(SELECT val FROM tableB)

每个表的定义: CREATE TABLE tableA(val INT,PRIMARY KEY使用HASH(val))ENGINE = MEMORY;

1 个答案:

答案 0 :(得分:1)

select
 a.val
from
 tableA a
left outer join tableB b on a.val = b.val
where
 b.val is null;

对250K行进行的一些额外测试表明,它们之间并不多:

call load_test_data();

call test_memory_tables_hash(); -- 0:00:00.597
call test_memory_tables_hash(); -- 0:00:00.362


call load_test_data();

call test_memory_tables_btree(); -- 0:00:00.460
call test_memory_tables_btree(); -- 0:00:00.429

完整的测试脚本:

drop table if exists tableA;
create table tableA
(
val int unsigned not null primary key
)
engine=innodb;

drop table if exists tableB;
create table tableB
(
val int unsigned not null primary key
)
engine=innodb;


drop procedure if exists load_test_data;

delimiter #

create procedure load_test_data()
proc_main:begin

declare i int unsigned default 0;
declare rnd int unsigned default 0;
declare max int unsigned default 250000;

  truncate table tableA;
  truncate table tableB;

  set autocommit = 0;

  while i < max do
    if i % 2 = 0 then insert into tableA values (i); end if;
    if i % 3 = 0 then insert into tableB values (i); end if;
    set i = i+1;
  end while;

  commit;

end proc_main #

delimiter ;

drop procedure if exists test_memory_tables_hash;

delimiter #

create procedure test_memory_tables_hash()
proc_main:begin

create temporary table mem_tableA 
(
  val int unsigned not null, index using hash(val)
) 
engine=memory select val from tableA;

create temporary table mem_tableB
(
  val int unsigned not null, index using hash(val)
) 
engine=memory;

insert into mem_tableA select val from tableA;
insert into mem_tableB select val from tableB;

select
 a.val
from
 mem_tableA a
left outer join mem_tableB b on a.val = b.val
where
 b.val is null
order by
 a.val desc
limit 64;

drop temporary table if exists mem_tableA;
drop temporary table if exists mem_tableB;

end proc_main #

delimiter ;

delimiter ;

drop procedure if exists test_memory_tables_btree;

delimiter #

create procedure test_memory_tables_btree()
proc_main:begin

create temporary table mem_tableA 
(
  val int unsigned not null, index using btree(val)
) 
engine=memory select val from tableA;

create temporary table mem_tableB
(
  val int unsigned not null, index using btree(val)
) 
engine=memory;

insert into mem_tableA select val from tableA;
insert into mem_tableB select val from tableB;

select
 a.val
from
 mem_tableA a
left outer join mem_tableB b on a.val = b.val
where
 b.val is null
order by
 a.val desc
limit 64;

drop temporary table if exists mem_tableA;
drop temporary table if exists mem_tableB;

end proc_main #

delimiter ;


call load_test_data();

call test_memory_tables_hash();
-- 0:00:00.597
call test_memory_tables_hash();
-- 0:00:00.362


call load_test_data();

call test_memory_tables_btree();
-- 0:00:00.460
call test_memory_tables_btree();
-- 0:00:00.429