2010-10-14 71 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