使用几个大向量过滤行

时间:2016-06-20 15:01:34

标签: java mysql

我有一个包含多个列的表A:

 A              B              C
 1              2              7  
 1              2              8 
 2              2              1 
 1              3              1 

我必须在Java中构建一个函数,它将3个向量作为输入,vA,vB,vC,并返回具有向量中任何值的行。这些数组用作过滤器。 A = {1,2,3,4}, b = {2}, C={7}将返回一行,但A = {1}, b = {2}, C={0}不会,因为列c中的行没有值0

  • 矢量太大,所以不可能像WHERE (c = ? OR c = ? ...c = ? )
  • 那样产生大量的OR。
  • 从SQL注入开始必须是安全的
  • 表现至关重要

其他线程(https://stackoverflow.com/a/1532454/1991779),建议临时表然后加入表。问题是我有几个向量来匹配几个列而不是一个。我想我可以创建一个表,插入所有值,然后使用

 WHERE A IN (SELECT A FROM TEMP ) AND B IN (SELECT B FROM TEMP ) AND  C
 IN (SELECT C FROM TEMP )

但是,我认为使用JOIN代替IN要快得多。有关Join而不是IN的建议。

有什么建议吗?

1 个答案:

答案 0 :(得分:1)

这使用cross join a.k.a.笛卡尔积(所有排列)的概念。因此,您的数组会生成一个派生表(在内存中),其行数为x*y*z,其中x,y,z是数组的大小。如果提供了大小为3,4和5的数组,则派生表的行数将为3 * 4 * 5 = 60。

您提供的产生一行的数组匹配仅为4 * 1 * 1 = 4

下面的

thing7是您正在搜索的主要表格。即使有大量数据,covering index也应该让这个东西飞起来。覆盖索引是通过索引的b树扫描给出所提供的信息,并且不需要读取数据页的索引。为什么?因为所需的数据在索引中。在你的情况下,非常薄。

表A B C用作数组。

唯一要说的是每个派生表都需要一个名称。所以我们在查询中给它起了名字xDerived。将派生表视为在内存中返回和使用的内容。它不是物理表。

模式

create table thing7
(   id int auto_increment primary key,
    A int not null,
    B int not null,
    C int not null,
    index(A,B,C) -- covering index (uber-thin, uber-fast)
);

insert thing7(A,B,C) values
(1,2,7),  
(1,2,8), 
(2,2,1), 
(1,3,1);

create table A
(   id int auto_increment primary key,
    value int
);
create table B
(   id int auto_increment primary key,
    value int
);
create table C
(   id int auto_increment primary key,
    value int
);

测试1

truncate table A;
truncate table B;
truncate table C;
insert A (value) values (1),(2),(3),(4);
insert B (value) values (2);
insert C (value) values (7);

select t7.* 
from thing7 t7  
join 
(   select A.value as Avalue, B.value as Bvalue, C.value as Cvalue 
    from A 
    cross join B 
    cross join C 
    order by a.value,b.value,c.value 
) xDerived 
on xDerived.Avalue=t7.A and xDerived.Bvalue=t7.B and xDerived.Cvalue=t7.C; 
+----+---+---+---+
| id | A | B | C |
+----+---+---+---+
|  1 | 1 | 2 | 7 |
+----+---+---+---+

...

测试2

truncate table A;
truncate table B;
truncate table C;
insert A (value) values (1);
insert B (value) values (2);
insert C (value) values (0);

select t7.*
from thing7 t7 
join
(   select A.value as Avalue, B.value as Bvalue, C.value as Cvalue
    from A
    cross join B
    cross join C
    order by a.value,b.value,c.value
) xDerived
on xDerived.Avalue=t7.A and xDerived.Bvalue=t7.B and xDerived.Cvalue=t7.C;
-- no rows returned

将此转换为基于会话的搜索非常容易。其中的概念是要搜索的数组(表A B C)具有会话列。然后它将促进多用户并发使用。但这是对答案进行过度设计,但询问您是否需要更多信息。