Rambler's Top100
Форум: MS ACCESSVBVBA MS OfficeMS SQL server
Новые сообщения: 0000

Форум: MS ACCESS

Вопросы связанные с MS ACCESS

Обновить визитку
Участники «Online»
Все участники

 
 

Доброго времени суток, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: оптимизация
 
 автор: osmor   (21.04.2011 в 18:14)   личное сообщение
 
 

Ну вот получил отчет о времени выполнения шагов про которые писал в
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!!!

  Ответить  
 
 автор: Силblч   (21.04.2011 в 18:48)   личное сообщение
 
 

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

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);


  Ответить  
 
 автор: osmor   (21.04.2011 в 20:34)   личное сообщение
 
 

Вложенные селекты работаю еще медленнее.
Left попробую.

  Ответить  
 
 автор: Силblч   (22.04.2011 в 10:23)   личное сообщение
 
 

в аксессе, скорее всего да

  Ответить  
 
 автор: Lukas   (21.04.2011 в 19:17)   личное сообщение
 
 


ON nz(tblNew.URN,"") = nz(tblOld.URN,"")


На таких объемах джойнить по вычисляемым полям весьма накладно.
А что, реально есть записи где URN Is Null?
Их надо отсекать и избавляться от Nz.

А поиском по рекордсету не быстрее будет?

Небольшой(Средний) образчик бы, для опытов.

  Ответить  
 
 автор: osmor   (21.04.2011 в 20:35)   личное сообщение
 
 

NZ уже не помню... надо посмотреть, может и правда можно убрать.
ФАйлик попробую подобрать

  Ответить  
 
 автор: Explorer   (21.04.2011 в 19:54)   личное сообщение
 
 

а через временные объекты реально или все нужно RealTime через прямой Update?
(ЗЫ в скобках на больших объемах я таким образом апдейтить не рискнул бы)

джойн на LEN = 255 и c NZ это действительно очень смелое решение - я бы так не смог :).

Осмор Монстр!

  Ответить  
 
 автор: osmor   (21.04.2011 в 20:33)   личное сообщение
 
 

Да уж монстр...
временные можно, там их уже ....

  Ответить  
 
 автор: Explorer   (21.04.2011 в 20:41)   личное сообщение
 
 

в общем случае некоторые рекомендуют (я не знаю конкретики, поэтому обобщаю, как обычно)

подготовить чистые данные
добавить чистые данные
грохнуть старые данные

UPDATE statement вообще говоря очень особенный инструмент - он оперирует ДАННЫМИ ЗАПИСИ
а нужно бы (если нет веских поводов к UPDATE и SET) оперировать самими ЗАПИСЯМИ ТАБЛИЦЫ

  Ответить  
 
 автор: Силblч   (22.04.2011 в 10:26)   личное сообщение
 
 

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

а я вот подумал, есть ли в аксессе возможность отключить транзакцию на апдейт?
он же, гад, место ищет, как та собачка, чтобы потом откат сделать, еси вдруг что...
а если надо апдейт сделать такой вот, однозначный, кагбэ, то можетможноотключить эту возможность?

и nz тоже не порадовали....

  Ответить  
 
 автор: osmor   (22.04.2011 в 11:36)   личное сообщение
 
 

ситуация такая
последовательно выполняются разные проверки.
Записи не прошедшие проверку обычно выдаются пользователю для реакции (как в данном случае, будут выведены записи которые я помечу ErrorID = 13)
пользователь может что-то поправить и повторить данную проверку или согласиться что все эти записи данную проверку не прошли и перейти к следующей проверке
Записи не прошедшие какую-то из проверок
а) не должны дальше проверяться в других проверках
б) после окончания всех проверок НЕ будут добавлены в рабочую (главную tblOLD) таблицу.
в) перед добавлением пользователь хочет увидеть все записи которые НЕ будут добавлены и по какой причине.

НИкаких других идей кроме как пометить на каждом этапе записи не прошедшие проверку определенным кодом ошибки не придумал :-(

  Ответить  
 
 автор: kot_k_k   (22.04.2011 в 11:52)   личное сообщение
 
 

а если сделать копию проверяемой - и записи НЕпрошедшие проверку из нее удалять, т.о. каждая последующая будет выполняться быстрее предыдущей,
в конце остануться только записи удоволетворяющие всем проверкам.

  Ответить  
 
 автор: Силblч   (22.04.2011 в 12:14)   личное сообщение
 
 

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

з.ы. Олег, лефт джоин попробывал?

  Ответить  
 
 автор: kot_k_k   (22.04.2011 в 12:29)   личное сообщение
 
 

зачем у нас же копия - вот отсутствующие в копии и будут не прошедшие проверку

  Ответить  
 
 автор: Силblч   (22.04.2011 в 12:31)   личное сообщение
 
 

та нипомню я уже всего задания :))

  Ответить  
 
 автор: osmor   (22.04.2011 в 12:31)   личное сообщение
 
 

Left еще не пробовал боюсь что до понедельника времени не будет

  Ответить  
 
 автор: Силblч   (22.04.2011 в 12:32)   личное сообщение
 
 

не бойся :) надеюсь лефт тебе поможет :))

  Ответить  
 
 автор: kot_k_k   (22.04.2011 в 12:37)   личное сообщение
 
 

а ты обещал пример выложить - нам же тож интересно

  Ответить  
 
 автор: osmor   (03.05.2011 в 09:48)   личное сообщение
 
 

ну в общем что получилось.
Заменил этот запрос 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 - зло (как будто и так не понятно было)

ЗЫ. Файл пока дать не могу

  Ответить  
 
 автор: Дядя Федор   (03.05.2011 в 11:46)   личное сообщение
 
 

Смоделировал ситуацию (поля заполнил случайными числами). Запросы взял твои (в первом удалил проверки на нулл и "") и вот.

Public Sub tstosmor()
Dim st&
st = apiTimeGetTime
CurrentDb.Execute ("qvr2osmor")
Debug.Print apiTimeGetTime - st
End Sub
'Результат 1266


с оригинальными запросами - 161108

Где здесь 12 минут?

ПС в последнем запросе поставил Left
ППС с inner 162488

Возможно, конечно, поля URN у тебя длинные. Но все равно непонятна разница в тесте.
Да, и я их (URN) сделал индексированными.....

  Ответить  
 
 автор: osmor   (03.05.2011 в 14:21)   личное сообщение
 
 

поля длинные текстовые в среднем 70 символов

  Ответить  
 
 автор: Lukas   (03.05.2011 в 18:49)   личное сообщение
 
 

qSelectNewObj:

select ... from tblNew WHERE  ErrorID=1 ...

Здесь отобрались записи с ErrorID=1...


UPDATE qSelectNewObj ... SET qSelectNewObj.ErrorID = 1

Здесь мы этим-же записям делаем ErrorID = 1. (но оно и так =1)

Или я недогоняю чего-то?

  Ответить  
 
 автор: Дядя Федор   (03.05.2011 в 22:31)   личное сообщение
 
 

это для теста

  Ответить  
 
 автор: Lukas   (03.05.2011 в 23:11)   личное сообщение
 
 

Аааа.
Там во втором запросе
... SET qSelectNewObj.ErrorID = 13
должно быть.

Попутно:
Может поиграться очередностью во Where в первом запросе?

Я бы попробовал так:
WHERE URN <> "" and ErrorID=1and Not (URN) Is Null

  Ответить  
 
 автор: osmor   (04.05.2011 в 07:58)   личное сообщение
 
 

Там во втором запросе
... SET qSelectNewObj.ErrorID = 13


ага, это я опечатался
у меня на работе access нет я по памяти писал.
с очередностью попробую.

  Ответить  
HiProg.com - Технологии программирования
Rambler's Top100 TopList