-
Можно ли как-то оптимальнее переписать процедуру?
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
-
если FB 2.1 умеет джойны в апдейтах, то выборку PATIENT_FIX_UID можно попробовать прямо в update включить. Но фактически это прирост в производительности вряд ли даст
-
>умеет джойны в апдейтах
пробовал - увы
-
делается в один запрос: update STUDIES set STUDY_INDEX = 102 where STUDIES.PATIENT_UID = (select PATIENT_UID...)
PATIENT_NAME_UPPER - точно уникально?
-
точнее: where STUDIES.PATIENT_UID = any(select PATIENT_UID...)
-
>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 01:30) [5] "patient_id_upper" - что это?
>не работают индексы, не подходит. оптимизатор определяет, использовать индекс или нет тем не менее, если считаете, что индекс здесь необходим - укажите это явным образом, а именно: ручками стабилизируйте план
-
>Дмитрий Белькевич © (08.10.14 01:30) [5] >знаю. можно было переписать на цикл выборок, но нет необходимости есть один просто закон: всё, что может случиться, случится и задача программиста заключается в том, чтобы это предусмотреть тем более, в данном случае это ни усложнит логику, ни повлияет на быстродействие, ни приведёт к избыточному кодированию но дело, конечно, ваше
-
>тем не менее, если считаете, что индекс здесь необходим - укажите это явным образом, а именно: ручками стабилизируйте план
как это можно сделать?
не то, что бы я считал, может, конечно, оптимизатору и виднее. но хранимка выполняется с использованием индекса, а с выборками в апдейте - без, понятно, что это плохо сказывается на скорости.
>но дело, конечно, ваше
хорошо, наверно перепишу.
patient_id_upper - это одно из полей таблицы patients, как и patient_id, по другому полю просто выборку сделал. разницы нет - индекс не работает и по patient_id.
-
>Дмитрий Белькевич © (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]" всплыло это поле соответственно, возникло подозрение, что вы утаиваете ещё какую-то информацию)
-
>явным указанием плана оптимизатору
спасибо, посмотрю.
>соответственно, возникло подозрение, что вы утаиваете ещё какую-то информацию)
ничего такого :) разные поля просто. их в таблице есть с десяток, которые не учавствуют в действе. не все с индексами за ненадобностью, но те, которое упоямнуты - с индексами.
-
пробовал разные индексы, у всех: 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))
-
собственно - смысл имел только foreign study.PATIENT_UID, rdb$foreign22, но и с ним - index cannot be used in the specified plan так что - останусь пока что с процедурой, может только for добавлю, других идей пока нет
-
where STUDIES.PATIENT_UID = (select PATIENT_UID...)
но понятно, что надо быть готовым ловить exception, когда "select PATIENT_UID..." вернёт более одной строки
-
ну, и альясы желательно писать всегда и везде
-
спасибо за ответы, буду разбираться :)
|