java - 过滤具有多个大 vector 的行

标签 java mysql

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

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

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

  • vector 太大,因此不可能生成大量 OR,例如 WHERE (c = ? OR c = ? ...c = ? )
  • 它必须能够避免 SQL 注入(inject)
  • 性能至关重要

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

 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 来完成此操作的建议。

有什么建议吗?

最佳答案

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

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

下面的

thing7 是您正在搜索的主表。即使其中有大量数据,覆盖索引也应该能让这个东西飞起来。覆盖索引是一种通过索引的 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

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

关于java - 过滤具有多个大 vector 的行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37925769/

相关文章:

mysql - PHP INNER JOIN 两个表ID匹配问题

mysql - SQL从两个表中获取对话

java - @ConditionalOnProperty 和 @Scheduled 不起作用

java - 如何使用 MockMvcResultMatchers.jsonPath

java - 提取 tar 文件

php - Mysql -> 拉取结果出现次数并显示在页面上

mysql - GROUP_CONCAT 中的 CONCAT - 如何删除重复结果

javascript - Magento通过ajax将数据插入数据库

java - 设置 Cassandra 代码格式化程序,options/code.style.schemes.xml 的用途是什么?

java - Type Erasure 抬头,如何规避?