|
|
|
"Курсорная болезнь" - что это такое и как от нее избавиться
|
|||
|---|---|---|---|
|
#18+
Неоднократно встречал такие фразы (употребляются обычно с негативным оттенком) как "метод курсорных переборов записей", "БД на курсорах" и т.п., но никак не могу понять, что это такое. Хорошо бы было, чтобы кто-нибудь разъяснил, что это такое, желательно с примерами, и рассказал бы, в чем вред этих методов и как от них избавиться. А то вдруг я этим болен, и не знаю об этом? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.12.2003, 20:25 |
|
||
|
"Курсорная болезнь" - что это такое и как от нее избавиться
|
|||
|---|---|---|---|
|
#18+
это когда вместо того написать SELECT COUNT(*) FROM my_table и получить результат через 0.00001 сек. пишут цикл и перебирают часами все записи, пытаясь подсчитать их количество. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.12.2003, 22:53 |
|
||
|
"Курсорная болезнь" - что это такое и как от нее избавиться
|
|||
|---|---|---|---|
|
#18+
А откуда такое словосочетание взялось и что, собственно, означает "курсор" в данном контексте? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.12.2003, 11:15 |
|
||
|
"Курсорная болезнь" - что это такое и как от нее избавиться
|
|||
|---|---|---|---|
|
#18+
Курсор использется для просмотра таблицы по строкам, как связь между реляционной моделью данных и моделью языков программирования. Так как при работе с курсором база должна хранить дополнительную информацию и обработка происходит не за один сеанс связи а за N то естественно скорость будет ниже. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.12.2003, 11:28 |
|
||
|
"Курсорная болезнь" - что это такое и как от нее избавиться
|
|||
|---|---|---|---|
|
#18+
Курсор, грубо говоря, это указатель на текущую запись. Когда используешь recordset, то имеешь доступ только к одной строке. Но перемещая курсор, можно последовательно получить доступ ко всей таблице. Наглядно представить это можно посмотрев на форму в обычном виде (Single Form). Ничего плохого в курсорах нет, просто применение их там где можно без них обойтись неразумно. Смотри пример Lepsik . Цикл по записям имеется в виду с помощью recordset'a ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.12.2003, 11:33 |
|
||
|
"Курсорная болезнь" - что это такое и как от нее избавиться
|
|||
|---|---|---|---|
|
#18+
А откуда такое словосочетание взялось и что, собственно, означает "курсор" в данном контексте? то идет от терминологии SQL сервера, когда для перебора записей вы открываете курсор - так вот оно там называется - вот примерчик - перебираем список таблиц - отнимаем все права, потом даем право на просмотр (для группы) Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.12.2003, 11:34 |
|
||
|
"Курсорная болезнь" - что это такое и как от нее избавиться
|
|||
|---|---|---|---|
|
#18+
Понял в общих чертах. Из этого следует, что я сам этой болезнью страдаю. Чтобы наметить пути избавления, приведу пример задачи, вдруг кто подскажет, как это сделать без курсоров? Есть таблица ТБЛ1(Поле1(PK), поле2, Поле3...) с данными, причем каждое значения каждого поля может содержать некорректности (в том смысле, что их содержимое не соотвтствует "Формату", заданному для каждого поля. Под "форматом" понимается либо определенное чило символов для строковых полей, либо определенный "вид" строки, например для определенных полей значение должно содержать определенную подстроку и т.п. Задача состоит в том, чтобы перенести в ТБЛ2 (структура та же) данные, соответствующие формату (прошедшие проверку). Строки, хотя бы одно значение любого поля которой не прошло проверку, должны быть помещены в ТБЛ3 (структура та же). В таблицу ТБЛ4(Поле1(FK),ИмяПоля, Сообщение_об_ ошибке) должны прописыватья сообщения о несоответствии формату, например, если в 10 строке входных данных в Поле5 данные не соответствуют формату, в строке ТБЛ4 должно быть: 10;Поле5;Ошибка:Должно быть 4 символа, а их 5 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.12.2003, 11:54 |
|
||
|
"Курсорная болезнь" - что это такое и как от нее избавиться
|
|||
|---|---|---|---|
|
#18+
2 Varan В данной задаче все будет зависет от того, какое соотношение кол-ва строк в таблице и кол-ва всех проверок по всем полям. Если кол-во проверок по всем полям больше чем кол-во строк в таблице, то более оптимальным вариантом будет как раз курсор. Если же кол-во строк в таблице на порядки превышает кол-во всех проверок, то более оптимальным будет примерно след. вариант (для T-SQL): - на каждую проверку выполняется if exists("запрос с условием не несоответствие заданным параметрам") если записи есть, тогда insert into tab4(...) select ... from tab1 where ("такое же условие как в запросе выше") - после всех проверок выполняется запрос insert into tab2(...) select ... from tab1 where ("перечисление всех условий") ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.12.2003, 12:10 |
|
||
|
"Курсорная болезнь" - что это такое и как от нее избавиться
|
|||
|---|---|---|---|
|
#18+
incold, "Если кол-во проверок по всем полям больше чем кол-во строк в таблице" - немного не понял, как может быть число проверок меньше числа строк? Например, в таблице 15 полей, 10 из них надо проверить если 1000 строк, то имеем 10000 проверок, т.е. число проверок = число строк*число проверяемых полей, что всегда больше числа строк при числе проверяемых полей>1 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.12.2003, 12:25 |
|
||
|
"Курсорная болезнь" - что это такое и как от нее избавиться
|
|||
|---|---|---|---|
|
#18+
Вот это и есть курсорная болезнь Число проверок всех полей, но проверяются они сразу по всем записям одним запросом. Если число полей 15, проверить нужно 10 полей. Выполняем 10 запросов на проверку каждого поля во всех записях. Т.е. число всех проверок равно 10. Другой вариант: число полей 15, нужно проверить 10 полей по 10 критериям - итого 100 проверок. Кол-во записей = порядка 100. В этом случае лучше (или без разницы) сделать цикл по всем записям и делать все проверки по каждой записи. Чем больше записей тем выгоднее переложить работу по работе с записями на СУБД. Надеюсь так понятнее. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.12.2003, 12:35 |
|
||
|
"Курсорная болезнь" - что это такое и как от нее избавиться
|
|||
|---|---|---|---|
|
#18+
Incold, Я уж чувствую, что заразился этой напстью :-) "число полей 15, нужно проверить 10 полей по 10 критериям - итого 100 проверок" Все ж таки мне не совсем понятно, что понимается как "проверка по критерию" Я под 1 проверкой имел в виду проверку одного значения одного поля. А Вы? Например мы имеем код типа такого, который возвращает результат проверки Function Proverka(arg as string)as boolean dim x1 as,X2 as ... X1=f(arg) select case X1 case Value_1 if ... Proverka=... else end if case value_2 if.. else end if case value_3 end select end function Это в Вашем понимании одна проверка или столько, сколько раз Case-ов и IF-ов в коде? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.12.2003, 12:47 |
|
||
|
"Курсорная болезнь" - что это такое и как от нее избавиться
|
|||
|---|---|---|---|
|
#18+
Ошибка:Должно быть 4 символа, а их 5 Кол-во проверок - это макисмальное число вот таких вот сообщений. И еще, я указывал, что свой пример привожу для Transact-SQL В MDB будет немного по другому. Общий смысл такой: если какое-то условие можно проверить одним оператором для всех записей сразу и общее число записей значительно превышает кол-во накладываемых условий на одну запись, то оптимальнее будет на проверку каждого условия выполнять запрос для всех записей. Пример который был на кол-во символов в поле (Transact-SQL): Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.12.2003, 13:02 |
|
||
|
"Курсорная болезнь" - что это такое и как от нее избавиться
|
|||
|---|---|---|---|
|
#18+
incold , Спасибо, как попробую SQL-вариант, расскажу какой скоростнее для моих данных. Даже если он и будет медленнее, в следующий раз думать буду, прежде чем по клаве долбить ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.12.2003, 13:15 |
|
||
|
"Курсорная болезнь" - что это такое и как от нее избавиться
|
|||
|---|---|---|---|
|
#18+
А зачем дважды мучать SELECT проверки ? Предлагаю подредактировать пример: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. Если требуется и в результате присутствия ошибок заносить верные данные в другую таблицу, то с скрипта нужно просто убрать IF. Насчет проверок - в принципе смотря что и зачем проверяется. Если просто проверяются значения полей, то тут самое удобное воспользоваться от case в селектах для примитивных условий до проверяющих функций. Кстати в данном случае приведения примера лично я считаю особого выигрыша запроса у курсорного варианта не будет - в обоих случаях сервер проведет table scan - причем для варианта с запросом скорее всего table scan будет проведен дважды по таблице из за использования функции Len(), а в случае полного перебора таблицы курсором получится всего один раз. Так что тут как ни странно в данном случае наоборот - курсор будет быстрее. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.12.2003, 13:56 |
|
||
|
"Курсорная болезнь" - что это такое и как от нее избавиться
|
|||
|---|---|---|---|
|
#18+
ASCRUS , спасибо. Оказывается, "курсоры" - не всегда зло! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.12.2003, 14:24 |
|
||
|
"Курсорная болезнь" - что это такое и как от нее избавиться
|
|||
|---|---|---|---|
|
#18+
2 ASCRUS Полностью согласен со всеми замечаниями .... Но ведь это же был пример, чтобы объяснить смысл понятия курсоров... хотя наверное не очень удачный. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.12.2003, 14:24 |
|
||
|
"Курсорная болезнь" - что это такое и как от нее избавиться
|
|||
|---|---|---|---|
|
#18+
Ну тут как всегда все относительно :) Например если предположить, что на таблицы tab3 и tab2 существуют триггеры на добавление, то вариант с запросом однозначно будет быстрее, так как эти триггеры при запросе будут вызваны по одному разу для каждой таблицы и можно будет спокойно обработать весь набор вставленных записей с Inserted одним запросом. В случае же курсора получится, что триггера будут вызываться столько раз, сколько записей в обрабатываемой таблице, что в случае какой то сложной обработки в триггерах приведет к существенному замедлению. Плюс стоит учитывать особенности каждой СУБД - например я сейчас работаю в Sybase ASA, где можно создавать индексы на системные функции, т.е. там спокойно можно создать индекс на Len(Field1) и соотвествующе избавиться от TABLE SCAN, перейдя на INDEX SCAN. Плюс как ни странно, но за свою практику проектирования БД я сто процентно убедился, что частенько приходится логику и структуру БД подгонять под конкретные требования клиентских приложений, причем под Access это одно, под Delphi - другое. Единственный инструмент, который на моей памяти может работать с "чистой" структурой БД, без логики, специально ориентированной на него - это Power Builder, но к сожалению у нас он распостранен только в крупных конторах, предпочитающих западное ПО. Так что мое личное мнение, что тут дело не сколько в курсорах, запросах и т.д., а в правильном понимании поставленной задачи архитектором БД, ее правильным решением с учетом самого ТЗ и использования сред разработки клиентских приложений. Например в приведенном в данном топике примере сразу возникает закономерный вопрос - зачем таблицу с данными разбивать на 2 таблицы, с правильными и ошибочными данными ? Не легче ли сделать просто таблицу с ключевым полем ID записи и в нее занести коды верных или ошибочных данных. Причем опять же, что лучше, стоит решать исходя из постановки задачи, чего меньше бывает в исходной таблице - верных или ошибочных записей. Если меньше ошибочных, то значит таблицу делаем для них: Код: plaintext 1. 2. 3. В итоге мы всегда можем быстро получить верные данные: Код: plaintext 1. 2. и ошибочные записи: Код: plaintext 1. 2. В итоге мы имеем всего один table scan по таблице Tab1, не занимаем лишнего места в БД двумя дублирующими записями таблицами вместе с основной , соотвествующе не делали лишних накладных расходов по физической записи на диск данных этих таблиц, ну и всегда сможем быстро получить правильные и ошибочные записи, так как оптимизатор MSSQL будет использовать алгоритм сканирования первичного ключа таблицы Errors, а если там не так много записей, то фактически и вообще первым же запросом загоним ее в кэш MSSQL и уже в дальнейшей серии нужных нам запросов будем работать с ее копией в памяти. Так что дело только в проектировании, знание релляционных основ, умение думать на SQL и мыслить абстрактно применительно к множествам. P.S. Я в этом плане за название не "Курсорная болезнь", а "Алгоритмическая болезнь", которой очень часто подверженны программисты, привыкшие алгоритмически обрабатывать множества данных путем разбиения процесса обработки данных на серию мелких пошаговых алгоритмов. Особенно этой болезни насколько я знаю подверженны многие программисты, привыкшие пошагово работать с наборами данных: дельфийцы, фокспрошники, парадоксники и т.д. В этом плане программистам Access должно быть легче, так как изначально Jet-движок Access был настоящим SQL-движком и им более привычны понятия манипулирования данными с помощью запросов. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.12.2003, 15:17 |
|
||
|
"Курсорная болезнь" - что это такое и как от нее избавиться
|
|||
|---|---|---|---|
|
#18+
оффтопик 2 ASCRUS Снимаю шляпу, и позвольте пожать Вашу руку ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.12.2003, 15:25 |
|
||
|
"Курсорная болезнь" - что это такое и как от нее избавиться
|
|||
|---|---|---|---|
|
#18+
incold Большое спасибо :) Я тут как бы оказался случаным гостем, по приглашению Varan , но в принципе темы проектирования БД для всех СУБД одинаковы, а вопрос оказался для меня интересным :) Мне кажется надо почаще такие вопросы выносить в форум "Проектирование БД", а то получается, что мы с вами живем на просторах одного сайта и почти никогда не пересекаемся, каждый обитая только в пределах своего рабочего форума. Я лично например очень частый гость и наблюдатель форума mssql, не смотря на то, что уже давно работаю не на нем, а Sybase ASA, и не только потому, что у этих СУБД много похожего, а именно из за обсуждаемых там вопросов и оригинальных решений, которые легко потом переводятся в плоскость собственной платформы разработки. Как говориться, своя каша конечно хорошо, но и не грех посмотреть, как коллеги других форумов кашу готовят :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.12.2003, 15:38 |
|
||
|
|

start [/forum/topic.php?fid=45&fpage=1706&tid=1677639]: |
0ms |
get settings: |
11ms |
get forum list: |
16ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
44ms |
get topic data: |
9ms |
get forum data: |
3ms |
get page messages: |
86ms |
get tp. blocked users: |
2ms |
| others: | 262ms |
| total: | 439ms |

| 0 / 0 |
