如何使用许多功能和分组依据来优化此sql?

时间:2018-11-08 09:37:38

标签: sql oracle query-performance

我有以下sql,我想从gene_info返回sample_info,从id_card_no返回person_info,从race返回person_info,然后gene_info中的sample_dna_gene

外键:person_info.id = sample_info.self_object_idsample_info.id = sample_dng_gene.sample_id

我要从id中提取sample_info的第一个,并从gene_info中提取sample_dna_gene的第一个,所以我可能需要使用group by,但看不到其他方式可以做到这一点。我还需要为其他列添加max()。这看起来效率低下,我想看看是否还有其他方法可以做到这一点。该数据库具有多达十亿条记录,因此速度很重要。

select to_char(sdg.gene_info), max(aa.pid), max(aa.idn), max(aa.r)
      from (select max(pi.person_name),
                   max(pi.id) pid,
                   si.id sid,
                   max(pi.id_card_no) idn,
                   max(pi.race) r
              from person_info pi
              join sample_info si
                on pi.id = si.self_object_id
             group by si.id) aa
      join sample_dna_gene sdg
        on sdg.sample_id = aa.sid
     where aa.pid in ('...')
     group by to_char(sdg.gene_info)

1 个答案:

答案 0 :(得分:0)

因此,第一件事是您需要限制检索到的人员的集合。这意味着where aa.pid in (...)实际上应该是where pi.id in ('...')

第二,应该有一种更有效的方法来限制sample_info记录的集合。最好应该有一些业务逻辑(采样日期?状态?)。但是您可以使用解析函数来获取最早的数据。

真的不确定为什么在外部查询中有GROUP BY。所有这些MAX()调用都不会更改结果集。只是不必要的循环浪费。

with aa as (
    select pi.person_name
           , pi.id as pid
           , pi.id_card_no
           , pi.race
           , si.id as sid
           , row_number() over (partition by pi.id order by si.self_object_id ) as rn
    from person_info pi
         join sample_info si
             on pi.id = si.self_object_id
   where pi.id in  ('...')
 )
select aa.pid
      , aa.person_name
      , aa.race
      , aa.id_card_no
      , sdg.gene_info
from aa
join sample_dna_gene sdg
    on sdg.sample_id = aa.sid
where aa.rn = 1 -- just get the first matched `sample_info.id` for each `person_info`.

一个缺点是,在编写SQL时,将值列表pi.id in ('...')注入子查询很容易,但是在通过诸如Spring之类的框架调用该SQL时,难度更大。但是,您应该首先专注于正确设置SQL,然后再担心如何运行它。