Конференция "Базы" » Оптимизировать код процедуры [FB 2.1]
 
  • Дмитрий Белькевич © (07.10.14 11:16) [0]
    Можно ли как-то оптимальнее переписать процедуру?


    create or alter procedure PATIENT_UPDATE (
       SEL_PATIENT_ID char(100),
       SEL_PATIENT_NAME_UPPER char(100))
    as
    declare variable PATIENT_FIX_UID integer;
    begin
     if (:SEL_PATIENT_ID <> '') then
     begin
       select PATIENT_UID
       from PATIENTS
       where PATIENT_ID = :SEL_PATIENT_ID
       into :PATIENT_FIX_UID;
     end
     else
     if (:SEL_PATIENT_NAME_UPPER <> '') then
     begin
       select PATIENT_UID
       from PATIENTS
       where PATIENT_NAME_UPPER = :SEL_PATIENT_NAME_UPPER
       into :PATIENT_FIX_UID;
     end
     update STUDIES
     set STUDY_INDEX = 102
     where STUDIES.PATIENT_UID = :PATIENT_FIX_UID and
           STUDY_INDEX = 0;
    end

  • junglecat © (07.10.14 11:35) [1]
    если FB 2.1 умеет джойны в апдейтах, то выборку PATIENT_FIX_UID можно попробовать прямо в update включить.
    Но фактически это прирост в производительности вряд ли даст
  • Дмитрий Белькевич © (07.10.14 12:41) [2]
    >умеет джойны в апдейтах

    пробовал - увы
  • Кщд © (07.10.14 13:18) [3]
    делается в один запрос:
    update STUDIES set STUDY_INDEX = 102
    where STUDIES.PATIENT_UID = (select PATIENT_UID...)

    PATIENT_NAME_UPPER - точно уникально?
  • Кщд © (07.10.14 13:19) [4]
    точнее: where STUDIES.PATIENT_UID = any(select PATIENT_UID...)
  • Дмитрий Белькевич © (08.10.14 01:30) [5]
    >update STUDIES set STUDY_INDEX = 102 where STUDIES.PATIENT_UID = (select PATIENT_UID...)

    пробую:


    update STUDIES set STUDY_INDEX = 102 where STUDIES.PATIENT_UID =
    any( select PATIENT_UID from patients where patient_id_upper = "1107")



    и так:


    update STUDIES set STUDY_INDEX = 102 where STUDIES.PATIENT_UID in ( select PATIENT_UID from patients where patient_id_upper = "1107")



    получается:

    PLAN (PATIENTS INDEX (RDB$PRIMARY1))
    PLAN (STUDIES NATURAL)

    не работают индексы, не подходит.

    так:

    EXECUTE PROCEDURE PATIENT_UPDATE("1107", "")

    работают.

    >PATIENT_NAME_UPPER - точно уникально?

    вообще в таблице оно неуникально. но хранимка будет вызваться только для уникальных - в переменную выборка иначе не влазит, база ошибку пишет - видел, знаю. можно было переписать на цикл выборок, но нет необходимости, т.к. по логике программы такую процедуру можно вызвать только для уникальных записей.
  • Кщд © (08.10.14 12:21) [6]
    >Дмитрий Белькевич ©   (08.10.14 01:30) [5]
    "patient_id_upper" - что это?

    >не работают индексы, не подходит.
    оптимизатор определяет, использовать индекс или нет
    тем не менее, если считаете, что индекс здесь необходим - укажите это явным образом, а именно: ручками стабилизируйте план
  • Кщд © (08.10.14 13:15) [7]
    >Дмитрий Белькевич ©   (08.10.14 01:30) [5]
    >знаю. можно было переписать на цикл выборок, но нет необходимости
    есть один просто закон: всё, что может случиться, случится
    и задача программиста заключается в том, чтобы это предусмотреть
    тем более, в данном случае это ни усложнит логику, ни повлияет на быстродействие, ни приведёт к избыточному кодированию
    но дело, конечно, ваше
  • Дмитрий Белькевич © (08.10.14 21:39) [8]
    >тем не менее, если считаете, что индекс здесь необходим - укажите это явным образом, а именно: ручками стабилизируйте план

    как это можно сделать?

    не то, что бы я считал, может, конечно, оптимизатору и виднее. но хранимка выполняется с использованием индекса, а с выборками в апдейте - без, понятно, что это плохо сказывается на скорости.

    >но дело, конечно, ваше

    хорошо, наверно перепишу.

    patient_id_upper - это одно из полей таблицы patients, как и patient_id, по другому полю просто выборку сделал. разницы нет - индекс не работает и по patient_id.
  • Кщд © (09.10.14 09:04) [9]
    >Дмитрий Белькевич ©   (08.10.14 21:39) [8]
    явным указанием плана оптимизатору: http://www.firebirdfaq.org/faq224/

    >patient_id_upper - это одно из полей таблицы patients
    в данном случае, конечно, и не должно влиять

    в посте "Дмитрий Белькевич ©   (07.10.14 11:16)" это поле не фигурировало
    в посте "Дмитрий Белькевич ©   (08.10.14 01:30) [5]" всплыло это поле
    соответственно, возникло подозрение, что вы утаиваете ещё какую-то информацию)
  • Дмитрий Белькевич © (09.10.14 22:15) [10]
    >явным указанием плана оптимизатору

    спасибо, посмотрю.

    >соответственно, возникло подозрение, что вы утаиваете ещё какую-то информацию)

    ничего такого :) разные поля просто. их в таблице есть с десяток, которые не учавствуют в действе. не все с индексами за ненадобностью, но те, которое упоямнуты - с индексами.
  • Дмитрий Белькевич © (09.10.14 23:17) [11]
    пробовал разные индексы, у всех: index  cannot be used in the specified plan.


    update STUDIES set STUDY_INDEX = 102 where STUDIES.PATIENT_UID in (select PATIENT_UID from patients where patient_id_upper = "1107")
    PLAN (STUDIES INDEX (rdb$primary9))

  • Дмитрий Белькевич © (09.10.14 23:26) [12]
    собственно - смысл имел только foreign study.PATIENT_UID, rdb$foreign22, но и с ним - index  cannot be used in the specified plan
    так что - останусь пока что с процедурой, может только for добавлю, других идей пока нет
  • Кщд © (10.10.14 07:21) [13]
    where STUDIES.PATIENT_UID = (select PATIENT_UID...)

    но понятно, что надо быть готовым ловить exception, когда "select PATIENT_UID..." вернёт более одной строки
  • Кщд © (10.10.14 07:21) [14]
    ну, и альясы желательно писать всегда и везде
  • Дмитрий Белькевич © (16.10.14 11:33) [15]
    спасибо за ответы, буду разбираться :)
 
Конференция "Базы" » Оптимизировать код процедуры [FB 2.1]
Есть новые Нет новых   [134427   +34][b:0][p:0.001]