繁体   English   中英

MyBatis和SQL,最佳性能查询

[英]MyBatis and SQL, best performance query

我知道这是执行查询的最佳方法,将以下内容链接起来。 我需要优化性能,并避免在DB(postgresql)中进行无用的操作。

用户将输入一系列过滤器,这些过滤器是两个值(“ id_meta”和“ value”),这将减少我从“ meta”表中提取的行数。 这些字段不是PK。

这是一个示例 ,该表具有更多列,但是那些是感兴趣的。

| id_meta | value      | id_ud |
| ------- |:----------:| -----:|
| 1       | pippo      | 45    |
| 2       | 10         | 45    |
| 3       | 21/05/2010 | 45    |
| 1       | pluto      | 35    |
| 2       | 14         | 35    |
| 3       | 22/05/2010 | 35    |

依此类推...如果用户输入了(1:pippo)和(2:14)对,则查询将返回0行,因为第一个过滤器(45)返回的id_ud没有(2:14) 。

它不能同时为同一个id_meta赋予不同的值,例如(1:pippo)AND(1:pluto)之​​类的事情是不可能的

因此,基本上每两个过滤器都是一个嵌套子查询,这些子查询减少了第一个结果集的数量。 如果用户提供3个过滤条件,我将进行3个子查询

select id_ud 
from meta 
where id_meta = 12 
      and value = '45'
      and id_ud in (select id_ud 
                    from meta 
                    where id_meta = 10 
                    and value = 1000 
                    and id_ud in (select id_ud 
                                  from meta 
                                  where id_meta = 6 
                                  and value = 'll'
                                 )
                   )

我需要计算返回的行数,还有另一个条件

select count(id_ud) 
from meta 
where id_ud in (select ID_UD 
                from documento 
                where stato = 'ACHIVIATO' 
                and id_cat_doc = 2)
and value= '2010' 
and id_meta = 12 and id_ud in (select id_ud 
                               from meta 
                               where id_meta = 10 
                               and value = 1000 
                               and id_ud in (select id_ud 
                                             from meta 
                                             where id_meta = 6 
                                             and value = 'll'
                                             )
                              );

因此,基本上,我必须使用MyBatis动态创建一个嵌套子查询并计算返回的值,如上面的最后一个示例。 有没有一种方法可以避免使用ANY,ALL,UNION或其他SQL构造的所有子查询,pherap?

谢谢,请随时添加更多详细信息,我不确定我是否清楚解释了我的问题...

更新

我正在尝试使用mybatis构建此查询

    select 
        count (id_ud)
    from 
        documento
    where
        stato = 'ARCHIVIATO'
        and id_categoria_documentale = #{param2, jdbcType=BIGINT}
        <foreach item="value" index="key" collection="param1.entrySet()" open=" and id_ud in ("
            separator=" and id_ud in (" close="))">
            select
                id_ud
            from
                meta
            where
                id_meta = #{key, jdbcType=INTEGER}
                and value = #{value, jdbcType=VARCHAR}
        </foreach>

其中param1是包含所有用户过滤器的地图对象。 我在添加正确的结束数时遇到问题)...有任何想法吗?

尝试这个

select count(id_ud) 
from meta mt1
join (select ID_UD from documento where stato = 'ACHIVIATO' and id_cat_doc = 2) doc on (doc.ID_UD = mt1.id_ud)
join (select id_ud from meta where id_meta = 10 and value = 1000 ) mt2 on (mt2.id_ud = mt1.id_ud)
join (select id_ud from meta where id_meta = 6 and value = 'll' )  mt3 on (mt3.id_ud = mt2.id_ud)
where value= '2010' and id_meta = 12

这应该更快。

编辑:另一种方式:

select count(id_ud) 
from meta mt1
join (select ID_UD from documento where stato = 'ACHIVIATO' and id_cat_doc = 2) doc on (doc.ID_UD = mt1.id_ud)
where (1=1) --always true 
or (value= '2010' and id_meta = 12) and (id_meta = 6 and value = 'll') and (id_meta = 10 and value = 1000) --user conditions

您可以在脚本/程序中建立动态查询

您的查询或多或少与标签搜索,全文搜索或约会搜索相同。 因此,使用针对此类情况已经优化的搜索方法是有意义的。

幸运的是,postgres支持的全文似乎很合适。

我建议将整个“元”表合并为表“ documento”中的一列,以表示标记。 我们将此列命名为“标签”。

对于id_ud = 45,它将包含“ 1 = pippo 2 = 14 3 = 21/05/2010”

为了说服全文搜索引擎将标记视为“单词”,您可能必须使用除“:”之外的其他内容,禁用词法分析和其他奇特的选项等。

这应该相当快。

由于您有日期,因此另一个选择是为这些日期提供表“ documento”中的真实列。 例如,如果您有发布日期,为什么不将其放在带有索引的列中? 这也将允许范围(日期之间...和...)搜索。 关系数据库喜欢将数据放在列中……这是标准的,也是最高效的……像您一样的“元”表总是很麻烦。

可以使用位图索引扫描来组合多个独立的列索引,这非常快。

另一种方法是将标签放在“ documento”表中,但在hstore中。 这样,一条记录的所有标记都在同一行上,并且可以在hstore中的键上使用部分索引。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM