Оптимизировать запрос при использовании разделов для визуализации - PullRequest
0 голосов
/ 25 февраля 2020

Итак, вот и все.

Я пишу запрос для клиента, чтобы визуализировать данные, которые он заполнил, для веб-форм, которые мы для него создали. Структура форм может состоять из нескольких вложенных записей (назовем их дочерними) к основной записи (назовем это родительской). Все дети имеют свои собственные формы, с разными полями и отдельно от родителя. Прямо сейчас наши данные хранятся таким образом, что данные из всех форм хранятся в одной и той же таблице, разделенной «идентификатором записи», который уникален для каждой заполняемой формы, и «идентификатором сущности», которая указывает, к какой именно форме принадлежат данные (будь то родитель или один из детей).

У нас есть отдельная таблица, в которой мы сохраняем все наши отношения.

Прямо сейчас мне нужно написать запрос, который соответствует отношению дочерних записей к родительской записи. У меня есть несколько дочерних форм внутри родительской формы, поэтому вы увидите Child_1 и Child_2. Клиент хочет, чтобы данные были как можно более сжатыми ... поэтому мы начали для них разделять данные, чтобы в одной строке у вас был Parent_Data_1, а затем первая запись во всех дочерних формах. Следующей строкой будет тот же Родитель СНОВА, ЕСЛИ есть вторая запись в одной из дочерних форм. Это будет продолжаться go до тех пор, пока в конкретном родительском элементе больше не будет дочерних форм, и следующая строка будет следующим Родителем (Родителем 2), выровненным по первой записи дочернего элемента в Родителе 2 и т. Д. И т. Д. ,

Это ЗНАЧИТЕЛЬНО замедляет время выполнения запроса. Я прошел секунд за 20 000 строк до 30 минут. У нас есть функциональность, позволяющая клиенту запускать «фильтры» в своих данных, поэтому они запускают запрос несколько раз в неделю, чтобы получить данные, которые они ищут ... но это не может занять столько времени, сколько это необходимо. сейчас же.

Есть какие-нибудь предложения?

Final Basi c Пример:

Row 1: Parent_Data_1  ... Child_1_Record_1_Data ... Child_2_Record_1_Data
Row 2: Parent_Data_1  ... Child_1_Record_2_Data ... Null (if there isn't more than one record for Child Form)
Row 3: Parent_Data_2  ... Child_1_Record_3_Data ... Child_2_Record_2_Data
Row 4: Parent_Data_2  ... Null                  ... Child 2_Record_3_Data
Row 5: Parent_Data_3  ... Child_1_Record_4_Data ... Child 2_Record_4_Data
Row 6: Parent_Data_3  ... Child_1_Record_5_Data ... Child 2_Record_5_Data
Row 7: Parent_Data_3  ... Child_1_Record_6_Data ... Null

Ниже приведены скелеты моих таблиц и урезанная версия запроса, который я использую:

Dat_Data_Lrg:

+--------------------+--------------------+--------+--------+-------------+
|     Entity_ID      |     Record_ID      | Data_1 | Data_2 | Entity_TYPE |
+--------------------+--------------------+--------+--------+-------------+
| Parent_Entity_ID   | Parent_Record_ID   |    123 |    456 |        2500 |
| Child_Entity_ID_1  | Child_Record_ID_1  |    223 |    556 |        2500 |
| Child_Entity_ID_2  | Child_Record_ID_2  |    323 |    656 |        2500 |
| Parent_Entity_ID_2 | Parent_Record_ID_2 |    423 |    756 |        2500 |
| Child_Entity_ID_1  | Child_Record_ID_3  |    523 |    856 |        2500 |
+--------------------+--------------------+--------+--------+-------------+

ref_references:

+--------------------+--------------------+--------------------+-------------------+
|  Entity_ID_Parent  |  Record_ID_Parent  |  Entity_ID_Child   |  Record_ID_Child  |
+--------------------+--------------------+--------------------+-------------------+
| Parent_Entity_ID   | Parent_Record_ID   | Child_Entity_ID_1  | Child_Record_ID_1 |
| Parent_Entity_ID   | Parent_Record_ID   | Child_Entity_ID_2  | Child_Record_ID_2 |
| Parent_Entity_ID   | Parent_Record_ID   | Child_Entity_ID_1  | Child_Record_ID_3 |
+--------------------+--------------------+--------------------+-------------------+

Dat_Record:

+--------------------+--------------------+--------------+----------------+--------+
|     Entity_ID      |     Record_ID      | Entity_Type  | Entity_Token   | STATE  |
+--------------------+--------------------+--------------+----------------+--------+
| Parent_Entity_ID   | Parent_Record_ID   |         2500 | Parent_Token   |      2 |
| Child_Entity_ID    | Child_Record_ID    |         2500 | Child_Token    |      2 |
| Child_Entity_ID_2  | Child_Record_ID_2  |         2500 | Child_Token_2  |      2 |
| Parent_Entity_ID_2 | Parent_Record_ID_2 |         2500 | Parent_Token   |      2 |
| Child_Entity_ID    | Child_Record_ID_3  |         2500 | Child_Token    |      2 |
+--------------------+--------------------+--------------+----------------+--------+

Финальный стол

SELECT
  A.RecID as RecID,
  A.Parent_Data_1 as Parent_Data_1,
  A.Parent_Data_2 as Parent_Data_2,
  Child_Detail.Child_1_Data_1 as Child_1_Data_1,
  Child_Detail.Child_1_Data_2 as Child_1_Data_2,
  Child_Detail.Child_2_Data_1 as Child_2_Data_1,
  Child_Detail.Child_2_Data_2 as Child_2_Data_2,

FROM (
  select
  ROW_NUMBER() OVER(Partition by inc.recid ORDER BY inc.recid) as rn,
  inc.recid as RecID,
   dddl1.Parent_Data_1 as Parent_Data_1,
   dddl1.Parent_Data_2 as Parent_Data_2,
  from
    Dat_Record inc, Dat_Data_Lrg dddl1
  where
    inc.Entity_TYPE = 2500 and inc.Entity_Token = 'SPILL_RECORDS' and inc.state < 3
    and dddl1.Entity_TYPE = inc.Entity_TYPE and dddl1.Entity_ID = inc.Entity_ID 
    dddl1.Record_ID  = inc.Record_ID  
 ) as A OUTER APPLY
 ( select n,
  B.Child_1_Data_1,
  B.Child_1_Data_2,
  C.Child_2_Data_1,
  C.Child_2_Data_2
  from (  select mn.n,  dr.Record_ID from msc_nums mn, dat_record dr where dr.Record_ID = A.RecID and 
  mn.n < = (select max(rw) from (select  count(*) rw from ref_references where Record_ID_Parent = dr.Record_ID group by Entity_ID_Child) as t1)
  ) AS SP
LEFT JOIN (
  SELECT distinct
    ROW_NUMBER() OVER(Partition by illref.Record_ID_Parent ORDER BY illref.Record_ID_Child) as rn,
    inc.Record_ID  as RecID,
    dddl2.Data_1 as Child_1_Data_1,
   dddl2.Data_2 as Child_1_Data_2
  from
    Dat_Record inc, Dat_Record ill, ref_references illref,
     Dat_Data_Lrg dddl2
  where
    inc.Entity_TYPE = 2500 and inc.Entity_Token = 'SPILL_RECORDS' and inc.state < 3
    and illref.Entity_ID_Child = 'Child_Entity_ID_1' and illref.Record_ID_Parent = inc.Record_ID
    and ill.Entity_TYPE = 2500 and ill.Entity_Token = 'Child_Token' and ill.state < 3 
    and ill.Record_ID = illref.Record_ID_Child and ill.Record_ID = dddl2.Record_ID
    and dddl2.Entity_TYPE = illref.Entity_TYPE and dddl2.Entity_ID = illref.Entity_ID_Child
    and dddl2.Record_ID = illref.Record_ID_Child) as B 
    ON (A.RecID = B.RecID AND B.rn=SP.n)
    LEFT JOIN (
  SELECT distinct
  ROW_NUMBER() OVER(Partition by illref.Record_ID_Parent ORDER BY illref.Record_ID_Child) as rn,
    inc.Record_ID as RecID,
   dddl3.Data_1 as Child_2_Data_1,
   dddl3.Data_2 as Child_2_Data_2
  from
    Dat_Record inc, Dat_Record ill, ref_references illref,
     Dat_Data_Lrg dddl3
  where
    inc.Entity_TYPE = 2500 and inc.Entity_Token = 'SPILL_RECORDS' and inc.state < 3
    and illref.Entity_ID_Child = 'Child_Entity_ID_2' and illref.Record_ID_Parent = inc.Record_ID
    and ill.Entity_TYPE = 2500 and ill.Entity_Token = 'Child_Token_2' and ill.state < 3 
    and ill.Record_ID = illref.Record_ID_Child and ill.Record_ID = dddl3.Record_ID
    and dddl3.Entity_TYPE = illref.Entity_TYPE and dddl3.Entity_ID  = illref.Entity_ID_Child
    dddl3.Record_ID = illref.Record_ID_Child ) as C 
    ON (A.RecID = C.RecID AND C.rn = SP.n) 
    ) AS Child_Detail
...