2010-10-14 76 views
0

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

问题是,它的速度很慢,因为(我认为)内存表使用散列而不是有序的键。

如何有效地执行它?目前我使用 SELECT VAL FROM TABLEA其中val NOT IN(SELECT VAL FROM tableB的)

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

+0

两个表中是Val索引? – 2010-10-14 10:43:13

+0

是的,两者都是相同的 – Nir 2010-10-14 11:07:23

回答

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