Как мне оптимизировать этот SQL с большим количеством функций и группировать по? - PullRequest
0 голосов
/ 08 ноября 2018

У меня есть следующий 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_id и sample_info.id = sample_dng_gene.sample_id

Я беру первое из id из sample_info и первое из gene_info из sample_dna_gene, поэтому мне нужно использовать группу скорее всего, и я не вижу других способов сделать это. Мне также нужно добавить 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 голосов
/ 08 ноября 2018

Итак, во-первых, вам нужно как можно скорее ограничить набор людей, которых вы получаете.Это означает, что 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`.

Одна загвоздка в том, что вставка списка значений - pi.id in ('...') - в подзапрос проста при написании SQL, но сложнее при вызове этого SQL через такие фреймворки, какВесна.Тем не менее, вы должны сначала сосредоточиться на правильности SQL, а потом беспокоиться о том, как его запустить.

...