Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Базы данных и репортинг > изменение данных


Автор: z-END 27.1.2005, 10:58
имеется БД (парадокс, через BDE) далее создается N копий потока, в котором выполняется нечто вроде такого (писал прям щас т.е. код может и не рабочий, но суть вроде ясна):
Код

Thread1.Execute:

repeat
1:  DataModule.Table1.Locate ('SomeFiled', SomeData, [loCaseInsensitive]);  
2:  DataModule.Table1.Field[xxx].Value := NewSomeData;
3:  Next (SomeData);
until Thread1.finish;

ЗЫ таблица индексированая, записей куча (ориентировочно 300 000).

Вопрос(ы):
1. наверное стоит как-нить отключить запись БД на диск (для увеличения быстродейтсвия)?
2. возможен вариант что после выполнения пункта 1, и до выполнения пункта 2 в первом потоке,второй поток выпонит пункт 1, тем самым сделав текущую запись отличной от необходимой для пункта 2 первого потока, если использоватьSynchronize(...), этого можно будет избежать или нет?
3. и вообще будет-ли работать данный механизм или искать другие способы?

Автор: Bes 27.1.2005, 11:00
Пардон, я как раз таки и не понял сути.
Вообще что нужно сделать?

Автор: z-END 27.1.2005, 11:08
Bes по-моему все понятоsmile
рассказываю по-подробней:
В БД содержится список различных действий:
| ДЕЙСТВИЕ | ФЛАГ |
Действие - то что нужно сделать
Флаг - отметка о выполнении
т.к. действия не взаимосвязаны то (для ускорения сего процесса) они выполняются (по крайней мере очень хочется) в разных потоках..

Автор: Bes 27.1.2005, 12:21
Ну ладно, проедположим понял. :-)
Я конечно не силен в теории баз данных, но мои соображения такие:
1) Если хочешь, чтобы база была быстрой - используй MSSQLServer2000
2) Даже если ты будешь использовать несколько потоков, это вряд ли добавит тебе скорости, потому что доступ происходит к одному и тому же файлу и сам механизм доступа к данным не сможет работать быстрее он просто по очереди будет отрабатывать разные потоки и суммарная производительность останется той же. Как в винде: либо одно приложение выполняется быстро, либо два, но медленнее.
Попробуй написать всего два приложения которые будут менять записи одна с начала, а другая с конца и посмотри что получится не в теории, а на практике.
3) Как решишь вопрос с параллельным доступом к таблице парадоХ? На сколько это уменьшит скорость.
4) Изменять данные ты собираешься по какому принципу?
Какие должны быть вычисления? Т.е. вычисления будут аналогичными для всех записей (например, все увеличить на 1) или каждая запись индивидуальна? Тогда откуда беруться сведенья об изменениях? это таблица или происходят какие-то события? Если ты борешься со скоростью, значит есть большие объемы, а большие объемы не могут быть случайными событиями... (ИИ?)

Видишь? Для решения проблемы слишком мало информации, поэтому объясняй. :-)

Автор: z-END 27.1.2005, 12:46
Продолжаем объясненияsmile

Цитата(Bes @ 27.1.2005, 12:21)
1) Если хочешь, чтобы база была быстрой - используй MSSQLServer2000

на форуме читал что BDE - самый мощный вариант для локальных БД (быстрее ADO в 2000 раз) данное было написано с сылкой на тест Vit'а и я ему очень склонен верить.
Цитата(Bes @ 27.1.2005, 12:21)
Даже если ты будешь использовать несколько потоков, это вряд ли добавит тебе скорости,

Почему ты так думаешь? действия которые выполняются в потоке могут занимать значительное время (а могут и нет), и я решая использовать потки не пытался ускорить запись в БД, я хотел ускорить выполнение самих действий, результат которых записывается в БД.


Цитата(Bes @ 27.1.2005, 12:21)
Как решишь вопрос с параллельным доступом к таблице парадоХ?

а причем тут парралальный доступ?! Сессия-то одна общая используется... Мне бы максимально ускорить поиск требуемой записи (по индексируему полю) и запись значений я вот и хотел узнать как отключить запись БД на диск (т.е. что-бы все изменения происходили в памяти до момента пока не будет вызван FulshBuffrers

Цитата(Bes @ 27.1.2005, 12:21)
Изменять данные ты собираешься по какому принципу?

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

Автор: Bes 27.1.2005, 13:03
Ага, ну понятно.
не отразится значит.... :-)
Ну тогда держи такой ответ?
Короче я бы посторался сконструировать запрос, который бы сразу все делал.
типа:
update table1 set newdate = olddate+calcdate where id in (select id from table2 where move>0)

цикл медленно - запрос быстро
P.S. это конечно если не важно как делаются вычисления.... :-)

Автор: z-END 27.1.2005, 13:47
пришел к выводу что это дохлая затеяsmile
для нормальной работы необходимо создавать к каждому потоку список в котором хранить индексы выполненных и предстоящий действий... т.к. потоки работая в одной сессии мешают друг другу постоянно меняя активную запись smile
Я вот думаю может просто создать для каждого потока свою таблицу с которой бы он и работал, а после завершения выполнять сверку данных (флага) и если зер гуд то менять его в основной таблице?
Если идея гуд то каким способом это можно реализовать? (т.е. выбрать все поля из основной таблицы удовлетворяющие требованиям THREAD_ID=..., и скопировать все данные в новую базу имя которой и передать потоку)

Автор: Bes 27.1.2005, 13:54
По-моему, ты сильно прикаываешься по потокам? :-))))
А вот на скул сервере такой проблемы не будет (про активную запись).
Да и вообще как-то задача поставлена размыто.
Ну будешь ты делать двойную работу и что? Как это изменит смысл...
Не знаю, не знаю... если бы не секретничал - тебе было бы проще помочь.
Или это твое ноу-хау? Дак в таком случае, свои изобретения нужно делать самому... :-)

Автор: z-END 27.1.2005, 14:16
да причем тут секреты? smile
просто код как таковой я еще не писал, все в стадии разработки, мозгую как лучше оформить...
Что имеется:
таблица пардох (строго через BDE) :
ID - индексированое поле (+)
OWNER - номер пользователя (подробности ниже=)
ACTION - код действия
PARAMS - параметры
FLAG - флаг (не выполнять, выполнить, выполнено, неудача)

Как отсюда видно, в таблице имеется список различных действий, каждое из которых привязано к конкретному пользователю (owner) действия может не выполнятся, тогда устанавливается флаг:=не выполнять, в противном случае флаг:=выполнить.
Действий этих куча, причем для каждого пользователя, как уже говорил выше эти действия могут занимать значительное время вплоть до нескольких минут, но на сам комп нагрузку они дают не сильную (работают через сеть) после выполнения каждого действия ему устанавливается флаг:=выполнено, или если произошла ошибка то флаг:=неудача.
Конечно можно все это делать и не через потоки, а все по очереди, ну уж очень логичным кажется для каждого ower'а создать поток в котором-бы и выполнялись все выше указанные шаги.

ЗЫ ждем эксперта по БД Vit'а в студию

Автор: Bes 27.1.2005, 14:56
Понял. Не вижу смысла делать через потоки, разве только из спортивного интереса...

Автор: z-END 27.1.2005, 15:38
Bes расскажи а как ты видишь смысл?! =)
Представть у пользователя 1000 действий (общее время выполнения 2 минуты), и пересчитаем все это ну скажем на 20 пользователей... получается уже 40 минут, а теперь представим насколько будет быстрее если для каждого использовать поток? ну 4 минуты (это максимум)...
И никакой это не спортивный интерес, а реальная оптимизация быстродействия.
Получается используя потоки мы ускоряем выполнение процесса в N-раз, так вот меня САБЖ волнует т.е.
1. быстрая запись в БД ( посредством какго-нить SuperCashMode=)
2. быстрый доступ к этой же БД (по первичному индексу)

Автор: Dimich 27.1.2005, 19:16
Прошу прощения, что вклиниваюсь в Ваш продуктивный диалог, но с z-END я согласен, что с потоками скорости должно прибавиться. Хотя геморно это... Вот если бы Paradox поддерживал хранимые процедуры (я не знаю и сомневаюсь очень сильно насчет этого), то задача бы через потоки решалась очччень просто и красиво!
А так надо хорошо продумать алгоритм, чтобы потоки не мешали друг-другу. Locate в потоке недопустим, если работаем через одну сессию. Сперва тут надо как бы определять фронт работы, а уже потом создавать потоки и раздавать потокам их задачи, выполнив которую он (поток) завершится и т.д.

Автор: z-END 27.1.2005, 19:27
Dimich и какие будут мысли по поводу "фронта работ", каждому свою таблицу, а всед за ними еще один поток запустить который-бы потихонечьку все изменения сделанные в дополнит таблицах вносил в основную таблицу?
блин у меня уже крыша едит (едит - всмысле не "TEdit" а "всмысле сносит напрочь" =)

Автор: Bes 28.1.2005, 07:35
2z-END: Щас объясню:
Я так понимаю что каждую секунду все 20 пользователей не совершают все 1000 действий т.е. скорость изменения базы не составит 20000записей/секунду.
Но даже если так, то у меня скул сервер и побыстрее работает.
Дальше, ты пишешь что не тысячу действий пользователя уходит 2 мин. Почему ты это время перемножаешь на количество пользователей - не понятно, ведь они могут совершать действия одновременно...
А это значит, что за 2 мин 20 пользователей могут совершить 20000 действий т.е. 10000 зап/мин или 167 зап /сек.
И что такая скорость в парадоксе недостижима без потоков?

2Dimich: Видимо я никак не могу вкурить в тему... :-( Не понимаю, что тут такое?...

Автор: Dimich 28.1.2005, 10:58
Может быть и я не въезжаю, но мысли я хотел предложить следующие:
1. Действия определяются таблицей пардох. Там очень много действий для ~20 пользователей. Процедура выполнения, пусть будет MakeAction (ID, OWNER, ACTION, PARAMS); будет выполняться с какой-то одной машины для всех пользователей/записей таблицы пардох с ID=min до ID=max, где флаг=ВЫПОЛНЯТЬ. Так?
2. Делаем селект:
SELECT * FROM пардох WHERE флаг = выполнять ORDER BY ID;
3. Пусть максимальное кол-во потоков будет MaxThread, тогда следуем следующей логике:
ПОКА ЕСТЬ НЕОБРАБОТАННЫЕ ЗАПИСИ СЕЛЕКТА
{
ЕСЛИ ПОТОКОВ < MaxThread ДЕЛАЕМ
{
СОЗДАЕМ ПОТОК;
ПОТОК.MakeAction (ID, OWNER, ACTION, PARAMS);
УБИВАЕМ ПОТОК;
}
}
Так думаю понятно? Думаю работать должно.

Автор: z-END 28.1.2005, 10:59
Bes ну я незнаю как тебе еще объяснить...передчитай внимательно.

Цитата(Bes @ 28.1.2005, 07:35)
каждую секунду все 20 пользователей не совершают все 1000 действий
пользователи вообще не совершают никаких действий, они просто записывают в БД необходимые дейтсвия и все, а уже потом, при нажатии на "педаль", выполняюся все действия и для всех пользователей ,а сами они (пользователи) уже к этому не имеет никакого отношения, теперь понятно?

Автор: z-END 28.1.2005, 11:13
Dimich да наеврно так и естьsmile

Цитата(Dimich @ 28.1.2005, 10:58)
таблицы пардох с ID=min до ID=max, где флаг=ВЫПОЛНЯТЬ. Так?

с одной оговоркой, каждый поток должен обрабатвать только 1 OWNER'а и по порядку т.к. могут быть взаимовытекающие (исключающие) действия.

в итоге надо хватать книжку по TQuery, я правильно понял? =)

Автор: Bes 28.1.2005, 11:58
Ааа..... :-)
А педаль кто нажимает? и как часто?
Может лучше постоянно делать по немножку по мере поступления, чем ждать пока все всё сгрузят и потом давить на педаль?
Короче видимо если с первого раза не дошло, то уже и не дойдет. :-)
Ну не понимаю, в чем трабл, видимо потому что сам не сталкивался.

Автор: z-END 28.1.2005, 12:23
Bes Конечно лучше поменемножку, но, увы специфика не позволяет выпонять таким образомsmile
ну вроде фронт, ясен, ктому-же провел пару тестов, время поиска и записи в БД, существенно ниже чем само выполнение задачи, так что с грехом по-полам, прокатитsmile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)