|
|
|
Такой случай...
|
|||
|---|---|---|---|
|
#18+
Доброе время суток, сегодня наткнулся на следующую проблему. Должна быть написана некая программа (C#), внутри которой будут работать паралельно множество threads (~ от 10 до 100). Каждый thread должен обращаться в БД и забирать свою "порцию" строк из довольно большой таблицы (около 1 миллиона записей) для обработки. Тут возникают сразу несколько вопросов: - конкурентноспособность, т.е. как избежать того, что бы 2 thread-а брали одни и те же строчки - чем лучше сделать (курсором?) - очень важна производительность Буду очень признателен за любые идеи ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2006, 15:07 |
|
||
|
Такой случай...
|
|||
|---|---|---|---|
|
#18+
В качестве одной из идей Сделать еще один трэд, который и будет ходить к БД, и никто кроме него, он будет отгребать порции данных и раздавать работу другим трэдам. Если обработка данных занимает больше времени чем их загрузка - вполне адекватное решение. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2006, 15:13 |
|
||
|
Такой случай...
|
|||
|---|---|---|---|
|
#18+
Подозреваю, с точки зрения производительности (которая, вроде как, очень важна) стоит убрать некую программу и делать все на сервере БД. Для случайно выбранной задачи это обеспечит такой прирост быстродействия, что не будет нужно ни тредов, ни чего либо еще. А иначе следующей задачей поставите кластер, чтобы распихать треды по разным машинам. Делать на сервере, наверное, можно и на C#, если он чем-то лучше. Ну а распараллеливать строки для обработки - зависит от. Самый простой способ - при наличии N потоков каждый из них делает Код: plaintext Впрочем, это далеко не самый эффективный вариант. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2006, 15:27 |
|
||
|
Такой случай...
|
|||
|---|---|---|---|
|
#18+
довольно хорошая идея, спасибо. А какой способ (из FAQ http://www.sql.ru/faq/faq_topic.aspx?fid=126) посоветуете что бы возвращать строчки ОТ..ДО? (опять же, важна производительность на очень большой таблице) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2006, 15:29 |
|
||
|
Такой случай...
|
|||
|---|---|---|---|
|
#18+
BigMacвнутри которой будут работать паралельно множество threads (~ от 10 до 100). ========== не обсуждается? Зачем потоки, т.к. голова процессора и голова пользователя ОДНА Каждый thread должен обращаться в БД и забирать свою "порцию" строк из довольно большой таблицы (около 1 миллиона записей) для обработки. ========= много решений, от: разбить таблицу на несколько/грязное_чтение/на_более_быстрый_диск/..........Тут возникают сразу несколько вопросов: - конкурентноспособность, т.е. как избежать того, что бы 2 thread-а брали одни и те же строчки =========== а чем плохо? При грязном чтении никто не конкурирует кроме головки на контроллёре диска HDD - чем лучше сделать (курсором?) ============= всегда плохо перед статикой-SELECT - очень важна производительность ======= определить узкое место (потоки/устр-во_вывода/обработка/......) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2006, 16:12 |
|
||
|
Такой случай...
|
|||
|---|---|---|---|
|
#18+
Вообще согласен с softwarer PS если используете MS SQL, читайте про READPAST ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2006, 16:46 |
|
||
|
Такой случай...
|
|||
|---|---|---|---|
|
#18+
softwarerПодозреваю, с точки зрения производительности (которая, вроде как, очень важна) стоит убрать некую программу и делать все на сервере БД. Для случайно выбранной задачи это обеспечит такой прирост быстродействия, что не будет нужно ни тредов, ни чего либо еще. А иначе следующей задачей поставите кластер, чтобы распихать треды по разным машинам. Ну, не всегда время обработки ограничивается только ресурсами системы... Впрочем, раз тредстартер это не упомянул, у него не такой случай.) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2006, 16:55 |
|
||
|
Такой случай...
|
|||
|---|---|---|---|
|
#18+
Уточните вопрос, пожалуйста. - Вам нужна очередь с однократной выборкой каждой поставленной в нее строки? - Или есть другие критерии, которые определяют, какие строки выбираются для какого потока? -Важно ли, чтобы строки выбирались на обработку в том порядке, в котором пришли. - Сколько строк за один раз выбирает поток? - Какова интенсивность добавления строк в таблицу? И вообще, какую задачу пытаетесь решить? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.07.2006, 19:48 |
|
||
|
Такой случай...
|
|||
|---|---|---|---|
|
#18+
Вот кстати, подобную задачу можно было бы довольно красиво решить, если бы в условии выборки можно было бы задать что-то вроде WHERE ... IS NOT LOCKED. Достаточно было бы из каждого потока делать запросы вроде SELECT ... WHERE ... IS NOT LOCKED LIMIT 1 FOR UPDATE (или, если хотите SELECT TOP 1 ... WHERE ... IS NOT LOCKED FOR UPDATE), конечно, при наличии row level locking. Однако я не знаю, есть ли возможность в какой-либо СУБД задать такое условие... Кто-нибудь в курсе о такой возможности?) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.07.2006, 20:38 |
|
||
|
Такой случай...
|
|||
|---|---|---|---|
|
#18+
В Oracle есть. Если мне не изменяет память, в одной из бесед упоминали про такую возможность и для MSSQL. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.07.2006, 23:58 |
|
||
|
Такой случай...
|
|||
|---|---|---|---|
|
#18+
Позволю себе процитировать не лучшее, но первое попавшееся под руку. How to Acquire a Lock without Handling Exceptions Overview Normally we use FOR UPDATE NOWAIT to acquire a lock on rows. This statement either locks all the selected rows or the control is returned without acquiring any lock (i.e. even on rows which are available for locking) after throwing an exception. For Update SKIP LOCKED But there is an feature in Oracle Database, the clause FOR UPDATE SKIP LOCKED, which can be used to lock rows that are available for locking and skip the rows that have been locked by other sessions. This statement returns the control back without throwing an exception, even if all the rows are locked by another session. To illustrate, we open two sessions. In the first session, we lock the row with deptno as 10 using FOR UPDATE NOWAIT. Код: plaintext 1. 2. 3. 4. 5. 6. In the second session, we try to lock two rows (deptno 10 and 20) from the table dept using FOR UPDATE NOWAIT. An exception is thrown after executing the following statement because one of the row (i.e. deptno 10) out of the selected list is already locked by session 1. Код: plaintext 1. 2. 3. 4. 5. 6. 7. Now we again try to lock two rows (deptno(s) 10 and 20) from the table dept but using the clause FOR UPDATE SKIP LOCKED instead of FOR UPDATE NOWAIT. As you can see the following statement has 1. returned the control without throwing an exception 2. acquired lock on the row (i.e. deptno 20) which is available for locking 3. skipped the row (i.e. deptno 10) that has been locked already by session 1 Код: plaintext 1. 2. 3. 4. 5. 6. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.07.2006, 00:03 |
|
||
|
Такой случай...
|
|||
|---|---|---|---|
|
#18+
Но, пожалуй, стоит отметить, что таскать с сервера по одной записи конкурирующими запросами - представляется мне одним из наименее эффективных возможных занятий. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.07.2006, 00:07 |
|
||
|
Такой случай...
|
|||
|---|---|---|---|
|
#18+
Ну, зависит от... Если сама обработка достаточно продолжительная, относительно обработки запроса СУБД -- почему бы и нет? Зато наверняка, особенно, если обработка идёт не многопоточным процессом, а несколькими процессами. Все процессы при этом абсолютно одинаковы, обработка распараллеливается на произольное количество обработчиков, если по каким-то причинам один из обработчиков помер в процессе, залоченная им запись освобождается по таймауту, и обрабатывается любым другим, не образуя гребёнку пропущеных записей и не требуя особой обработки подобной ситуации. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.07.2006, 00:16 |
|
||
|
Такой случай...
|
|||
|---|---|---|---|
|
#18+
DocAlНу, зависит от... Если сама обработка достаточно продолжительная, относительно обработки запроса СУБД -- почему бы и нет? Во-первых, я не особо в это верю - в этом случае автора вряд ли так уж интересовала бы эффективность именно работы с БД. Во-вторых, такая схема имеет смысл скорее не при продолжительной обработке, но при непредсказуемой по времени обработке - когда один процесс может застрять неожиданно надолго. В частности, именно эта схема употребляется в Oracle при обработке очередей. DocAlЗато наверняка, особенно, если обработка идёт не многопоточным процессом, а несколькими процессами. Хм. C# и fork() - малость из разных партитур :) DocAlесли по каким-то причинам один из обработчиков помер в процессе, Хм. А может программировать так, чтобы этого не случалось? DocAlи обрабатывается любым другим, не образуя гребёнку пропущеных записей и не требуя особой обработки подобной ситуации. И без этого будет все то же самое. Естественный результат обработки - простановка флага "обработано"; запись без этого флага подхватится любым процессом, который вновь потянется за следующей порцией данных. В то же время такой процесс естественно подразумевает и коммиты по каждому чиху; для Oracle такой режим не слишком удачен в смысле эффективности, да и, подозреваю, для любого другого сервера тоже (коммит означает одно из двух - либо необходимость гарантированно сбросить на диск все данные транзакции, то есть журнал, либо возможность потерять данные закоммиченной транзакции, что совершенно недопустимо). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.07.2006, 00:26 |
|
||
|
Такой случай...
|
|||
|---|---|---|---|
|
#18+
softwarer DocAlесли по каким-то причинам один из обработчиков помер в процессе, Хм. А может программировать так, чтобы этого не случалось? М... Если имеется в виду, "так, чтобы обработчики не помирали", это не всегда зависит от разработчика, если же "чтобы помирание как-то обрабатывалось", создавать также некого пастуха, то не всегда это и надо. softwarer DocAlи обрабатывается любым другим, не образуя гребёнку пропущеных записей и не требуя особой обработки подобной ситуации. И без этого будет все то же самое. Естественный результат обработки - простановка флага "обработано"; запись без этого флага подхватится любым процессом, который вновь потянется за следующей порцией данных. В то же время такой процесс естественно подразумевает и коммиты по каждому чиху; для Oracle такой режим не слишком удачен в смысле эффективности, да и, подозреваю, для любого другого сервера тоже (коммит означает одно из двух - либо необходимость гарантированно сбросить на диск все данные транзакции, то есть журнал, либо возможность потерять данные закоммиченной транзакции, что совершенно недопустимо). Ммм... А оракл не позволяет выставлять стратегию сохранения логов транзакции для отдельной сессии? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.07.2006, 00:53 |
|
||
|
Такой случай...
|
|||
|---|---|---|---|
|
#18+
Да, забыл добавить, в предложенном вами в этой ветке методе, то есть, при распределении записей по остатку от деления нацело, то в нём никто не подхватит. Хотя, конечно, как вы и указали, это не единственный возможный вариант. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.07.2006, 00:58 |
|
||
|
Такой случай...
|
|||
|---|---|---|---|
|
#18+
DocAlМ... Если имеется в виду, "так, чтобы обработчики не помирали", это не всегда зависит от разработчика, Хм. Если полагать, что "не использовать левых библиотек" итп зависит от разработчика, то скорее таки всегда. На практике - я делал такое серверное приложение, и начальство скомандовало использовать для слежения за ним ранее написанного "пастуха". В итоге от этой мысли отказались, потому что "пастух" периодически умирал, в то время как мое приложение - работало :) DocAlМмм... А оракл не позволяет выставлять стратегию сохранения логов транзакции для отдельной сессии? Позволяет. Насколько я понимаю, это один из шагов в сторону облегчения работы криво написанных приложений, наподобие того же параметра cursor_sharing. Но это не значит, что этот режим стоит использовать. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.07.2006, 08:22 |
|
||
|
Такой случай...
|
|||
|---|---|---|---|
|
#18+
DocAlДа, забыл добавить, в предложенном вами в этой ветке методе, Хм. Я бы предпочел какое-нибудь другое слово, например "упомянутом". "Предложенном" - подразумевает положительное отношение к этому методу, в то время как я решительно не готов считать его удачным. DocAlто есть, при распределении записей по остатку от деления нацело, то в нём никто не подхватит. С какой это стати? Тот же процесс и подхватит. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.07.2006, 08:26 |
|
||
|
Такой случай...
|
|||
|---|---|---|---|
|
#18+
softwarer DocAlМ... Если имеется в виду, "так, чтобы обработчики не помирали", это не всегда зависит от разработчика, Хм. Если полагать, что "не использовать левых библиотек" итп зависит от разработчика, то скорее таки всегда. На практике - я делал такое серверное приложение, и начальство скомандовало использовать для слежения за ним ранее написанного "пастуха". В итоге от этой мысли отказались, потому что "пастух" периодически умирал, в то время как мое приложение - работало :) DocAlМмм... А оракл не позволяет выставлять стратегию сохранения логов транзакции для отдельной сессии? Позволяет. Насколько я понимаю, это один из шагов в сторону облегчения работы криво написанных приложений, наподобие того же параметра cursor_sharing. Но это не значит, что этот режим стоит использовать. Ну, мы с вами просто работаем в разных областях, со своей спецификой, у вас, видимо, все данные для обработки уже имеются на сервере, хранятся в упорядоченном виде в СУБД, и конечно тут скорость обработки зависит практически исключительно от системых ресурсов, выделенных на это, а надёжность этой обработки полностью в руках разработчика. Но так бывает не всегда. С другой же стороны, мне не очень понятно, почему, если категорически недопустимо потерять результат обработки каждой записи, не дёргать-таки сервер коммитом, после этой самой обработки, а если это не столь принципиально -- то не заставлять сервер сбрасывать на диск лог транзакций "от каждого чиха". Да, можно, конечно, просто дёргать его не каждый чих, а каждый десятый, или там, каждый сотый чих, но это ведь симптоматическое лечение, всегда есть шанс потерять результаты обработки 9 (99) записей, да и почему бы серверу самому не разобраться, когда ему дёргаться? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.07.2006, 20:17 |
|
||
|
|

start [/forum/topic.php?fid=32&msg=33843737&tid=1545152]: |
0ms |
get settings: |
5ms |
get forum list: |
10ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
385ms |
get topic data: |
8ms |
get forum data: |
2ms |
get page messages: |
36ms |
get tp. blocked users: |
1ms |
| others: | 199ms |
| total: | 650ms |

| 0 / 0 |
