|
|
|
| Ну вот получил отчет о времени выполнения шагов про которые писал в
http://hiprog.com/forum/read.php?id_forum=2&id_theme=8919&page=1
теперь прошу помощи в оптимизации
есть две таблицы одинаковой структуры
одна главная (tblOld)
вторая содержит записи которые будут в последствии добавлены в главную (tblNew)
Сколько точно записей в таблицах не знаю но попробую уточнить
В обеих есть текстовое поле urn (255 символов) нужно в таблице tblNEW отметить записи у которых значение в поле urn уже есть в таблице tblOLD и в которых поле ErrorID = 1
Делал в лоб
есть запрос:
UPDATE tblNew INNER JOIN tblOld ON nz(tblNew.URN,"") = nz(tblOld.URN,"") SET tblNew.ErrorID = 13
WHERE tblNew.ErrorID=1;
|
От выполняется 31 час.
HELP ME!!! | |
|
| |
|
|
|
| а чего - иннер джоин?
кстати, попробуй лефтджоин с отсечением нулл по ненайденным.
на оракле оно быстрее работает чем джоин.... мы проверялли :)
поля, по которым мэчицца - индексные?
а так, пока што хз, только варианты разные пробовать еси шо
например
UPDATE tblNew
left JOIN tblOld ON nz(tblNew.URN,"") = nz(tblOld.URN,"")
SET tblNew.ErrorID = 13
WHERE tblNew.ErrorID=1 and nz(tblOld.URN,"")="";
|
UPDATE tblNew
SET tblNew.ErrorID = 13
WHERE tblNew.ErrorID=1
and exists(select 1 from tblOld where nz(tblOld.URN,"")=nz(tblNew.URN,""));
|
UPDATE tblNew
SET tblNew.ErrorID = 13
WHERE tblNew.ErrorID=1
and nz(tblNew.URN,"") in (select nz(tblOld.URN,"") from tblOld);
|
| |
|
| |
|
|
|
| Вложенные селекты работаю еще медленнее.
Left попробую. | |
|
| |
|
|
|
| в аксессе, скорее всего да | |
|
| |
|
|
|
|
ON nz(tblNew.URN,"") = nz(tblOld.URN,"")
|
На таких объемах джойнить по вычисляемым полям весьма накладно.
А что, реально есть записи где URN Is Null?
Их надо отсекать и избавляться от Nz.
А поиском по рекордсету не быстрее будет?
Небольшой(Средний) образчик бы, для опытов. | |
|
| |
|
|
|
| NZ уже не помню... надо посмотреть, может и правда можно убрать.
ФАйлик попробую подобрать | |
|
| |
|
|
|
| а через временные объекты реально или все нужно RealTime через прямой Update?
(ЗЫ в скобках на больших объемах я таким образом апдейтить не рискнул бы)
джойн на LEN = 255 и c NZ это действительно очень смелое решение - я бы так не смог :).
Осмор Монстр! | |
|
| |
|
|
|
| Да уж монстр...
временные можно, там их уже .... | |
|
| |
|
|
|
| в общем случае некоторые рекомендуют (я не знаю конкретики, поэтому обобщаю, как обычно)
подготовить чистые данные
добавить чистые данные
грохнуть старые данные
UPDATE statement вообще говоря очень особенный инструмент - он оперирует ДАННЫМИ ЗАПИСИ
а нужно бы (если нет веских поводов к UPDATE и SET) оперировать самими ЗАПИСЯМИ ТАБЛИЦЫ | |
|
| |
|
|
|
| кстати да
мы практикуем инсерт, вместо апдейта, где это возможно
ну или хинтами всякими, но это же не аксесс
а вот в последнее время мерж прикольно тоже работает
а я вот подумал, есть ли в аксессе возможность отключить транзакцию на апдейт?
он же, гад, место ищет, как та собачка, чтобы потом откат сделать, еси вдруг что...
а если надо апдейт сделать такой вот, однозначный, кагбэ, то можетможноотключить эту возможность?
и nz тоже не порадовали.... | |
|
| |
|
|
|
| ситуация такая
последовательно выполняются разные проверки.
Записи не прошедшие проверку обычно выдаются пользователю для реакции (как в данном случае, будут выведены записи которые я помечу ErrorID = 13)
пользователь может что-то поправить и повторить данную проверку или согласиться что все эти записи данную проверку не прошли и перейти к следующей проверке
Записи не прошедшие какую-то из проверок
а) не должны дальше проверяться в других проверках
б) после окончания всех проверок НЕ будут добавлены в рабочую (главную tblOLD) таблицу.
в) перед добавлением пользователь хочет увидеть все записи которые НЕ будут добавлены и по какой причине.
НИкаких других идей кроме как пометить на каждом этапе записи не прошедшие проверку определенным кодом ошибки не придумал :-( | |
|
| |
|
|
|
| а если сделать копию проверяемой - и записи НЕпрошедшие проверку из нее удалять, т.о. каждая последующая будет выполняться быстрее предыдущей,
в конце остануться только записи удоволетворяющие всем проверкам. | |
|
| |
|
|
|
| токо не удалять, а кидать во временную таблу, к записям, не прошедшим проверку, чтобы потом пользователю показать.... но может это будет дольше, чем просто маркер ставить?
з.ы. Олег, лефт джоин попробывал? | |
|
| |
|
|
|
| зачем у нас же копия - вот отсутствующие в копии и будут не прошедшие проверку | |
|
| |
|
|
|
| та нипомню я уже всего задания :)) | |
|
| |
|
|
|
| Left еще не пробовал боюсь что до понедельника времени не будет | |
|
| |
|
|
|
| не бойся :) надеюсь лефт тебе поможет :)) | |
|
| |
|
|
|
| а ты обещал пример выложить - нам же тож интересно | |
|
| |
|
|
|
| ну в общем что получилось.
Заменил этот запрос 2-мя
Первый "qSelectNewObj" для отбора нужных
select URN, ErrorID from tblNew WHERE ErrorID=1 and Not (URN) Is Null and URN <> ""
|
второй для обновления тех у которых URN в двух таблицах совпадает
UPDATE qSelectNewObj INNER JOIN tblOld ON qSelectNewObj.URN = tblOld.URN SET qSelectNewObj.ErrorID = 1
|
на таблицах
tblOld - 403 497 записей
tblNew - 112 057 записей
отработал за 12 с копейками минут
так что NZ в join - зло (как будто и так не понятно было)
ЗЫ. Файл пока дать не могу | |
|
| |
|
|
|
| Смоделировал ситуацию (поля заполнил случайными числами). Запросы взял твои (в первом удалил проверки на нулл и "") и вот.
Public Sub tstosmor()
Dim st&
st = apiTimeGetTime
CurrentDb.Execute ("qvr2osmor")
Debug.Print apiTimeGetTime - st
End Sub
'Результат 1266
|
с оригинальными запросами - 161108
Где здесь 12 минут?
ПС в последнем запросе поставил Left
ППС с inner 162488
Возможно, конечно, поля URN у тебя длинные. Но все равно непонятна разница в тесте.
Да, и я их (URN) сделал индексированными..... | |
|
| |
|
|
|
| поля длинные текстовые в среднем 70 символов | |
|
| |
|
|
|
| qSelectNewObj:
select ... from tblNew WHERE ErrorID=1 ...
|
Здесь отобрались записи с ErrorID=1...
UPDATE qSelectNewObj ... SET qSelectNewObj.ErrorID = 1
|
Здесь мы этим-же записям делаем ErrorID = 1. (но оно и так =1)
Или я недогоняю чего-то? | |
|
| |
|
|
|
|
| Аааа.
Там во втором запросе
... SET qSelectNewObj.ErrorID = 13
должно быть.
Попутно:
Может поиграться очередностью во Where в первом запросе?
Я бы попробовал так:
WHERE URN <> "" and ErrorID=1and Not (URN) Is Null | |
|
| |
|
|
|
| Там во втором запросе
... SET qSelectNewObj.ErrorID = 13
|
ага, это я опечатался
у меня на работе access нет я по памяти писал.
с очередностью попробую. | |
|
| |