|
![]() |
#1 |
Участник
|
Коллеги, я не программист, но разве так нельзя?
X++: while select table1 { i++; ttsbegin; table1.selectForUpdate(true); table1.reread(); table1.Field1 = strfmt("Blah %1", i); table1.doupdate(); ttscommit; }
__________________
Ivanhoe as is.. |
|
![]() |
#2 |
Участник
|
Можно, но reread = дополнительный select, что может оказаться накладным. К слову сказать если гарантировать отсутствие конфликтов (например запускать обработку на свободной базе), то можно попробовать и без него
![]() ![]() Обнаруженное поведение while select'а - это явный баг. Есть ещё вариант попробовать переписать цикл с использованием select ... next. В принципе то же самое, только вид сбоку, но кто его знает ... |
|
![]() |
#3 |
Участник
|
Я пытаюсь избавиться от двух зол: 1) отдельный ttsbegin/ttscommit для каждой записи (из 700 000 в одной таблице) 2) единственный ttsbegin/ttscommit для всей таблицы (700 000 записей) Оптимальным решением было бы разбить таблицу на, скажем, 70 кусков, т.е. изменить все записи за 70 транзакций. Для таблиц с уникальным индексом по единственному полю я, вроде, решение нашел, завтра продолжу тестирование. Для остальных, если не извращаться, надо будет выбрать (1) или (2). При гипотетическом отсутствии других вариантов какой из этих двух вариантов будет оптимальнее, кто как думает? Последний раз редактировалось Hyper; 05.04.2011 в 21:20. |
|
![]() |
#4 |
Moderator
|
Цитата:
Код: for(i=0;i<70;i++) { ttsbegin; while select forupdate table1 where (table1.recid mod 70)==i { .... table1.update(); } ttscommit; } |
|
![]() |
#5 |
Участник
|
|
|
![]() |
#6 |
Участник
|
Цитата:
В зависимости от версии SQL, от выставленного Recovery Model и от размера файла для логов. легко. для SQL - это не страшные объемы. Цитата:
Цитата:
возвращаемся к параметрам. 1. Если у вас SQL2000, то там есть блокировка на чтение. (или более старший SQL, но у вас установлен режим совместимости с SQL2000). только тогда имеет смысл заниматься "разбиением на, скажем, 70 кусков" Если же у вас более новый SQL, то заниматься ерундой не стоит. 2. Если у вас Recovery Model = Full, то на сколько бы кусков вы ни разбивали, все будет записываться в Transaction log. Если у вас Recovery Model = Simple, то вы выигрываете только на том, что каждая транзакция сразу очищается И файл транзакций НЕ растет. 3. вот и приходим к размеру лога. как вы изящно выразились "при достижении определенного порога все еле ворочается". просто транзакция заполняет весь лог, и СКЛ начинает увеличивать файл лога. на увеличение файла тратит значительное время. в SQL Management Studio вы можете посмотреть отчет (по-моему, Disk Usage) и ужаснуться сколько времени SQL тратит на увеличение размера. кроме того, исходя из своего опыта рискну предположить, что у вас таки SQL2005 или выше и параметры для файлов выставлены по-умолчанию. Дело в том, что начиная с SQL2005 файл Transaction Log по умолчанию растет по 1Мб (один мегабайт! - это ужасный параметр по умолчанию) =============== следовательно, перестаньте заниматься фигней. 700тыс записей - смешной объем как для Аксапты, так и для СКЛ. посмотрите в параметры СКЛ. прежде всего увеличьте минимальный размер Transaction Log до вменяемого значения (поставьте гиг 5) обязательно установите вменяемый размер прироста в фиксированных единицах (например, по 200-300Мб). Ни в коем случае не оставляйте по 1Мб. Так вы сократите фрагментацию как диска, так и внутреннюю SQL. Так вы минимизируете накладные расходы времени на рост Transaction Log. И не парьтесь "кусками". Сделайте или в одной нормальной транзакции. Или сделайте транзакцию на каждую запись. Разница только логическая - если прервете обработку, то либо отменятся все изменения, либо останется то, что сделано. |
|
|
За это сообщение автора поблагодарили: Hyper (1), sukhanchik (2), Poleax (1). |