![]() |
|
![]() ![]() ![]() |
|
budg |
|
|||
Новичок Профиль Группа: Участник Сообщений: 16 Регистрация: 21.12.2005 Репутация: нет Всего: нет |
ADO, MSSQL2000
Прошу подсказать вариант быстрого перехода по номеру записи в базе(таблице). Сейчас использую "MoveBy(n)", однако, при n=200000 (или даже 100000) переход занимает очень много времени - десятки минут. Причем заметил - от мощности сервера зависит слабо. Есть ли другие, не-MoveBy варианты? Заранее спасибо. ![]() |
|||
|
||||
Vit |
|
|||
![]() Vitaly Nevzorov ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 10964 Регистрация: 25.3.2002 Где: Chicago Репутация: 14 Всего: 207 |
Мдя, тяжёлый случай.... Общие рекомендации такие:
1. Забыть даже о возможности существования компонента TADOTable, а помнить что есть только TADOQuery 2. Забыть о существовании каких-то номеров записи, их нет и быть не может, таблица это не массив чтоб к записи обращаться по номеру. У вас должно быть поле в таблице которое каждую запись идентифицирует, например автоинкремент и по нему ключ. Если нет - добавить. 3. Использовать SQL запрос для получения данных из конкретной записи 4. Забыть о возможности чтения более десятка записей одним запросом, чтение миллиона записей... это нечто... Вы будете приятно удивлены что ваши "минуты" при переходе плавно превратятся в дни при запуске нескольких экземпляров программы на одной базе данных... 5. Прочитать вот эту статью: http://vingrad.ru/ART-DELPHI-002171 -------------------- With the best wishes, Vit I have done so much with so little for so long that I am now qualified to do anything with nothing Самый большой Delphi FAQ на русском языке здесь: www.drkb.ru |
|||
|
||||
budg |
|
||||
Новичок Профиль Группа: Участник Сообщений: 16 Регистрация: 21.12.2005 Репутация: нет Всего: нет |
Согласен - случай тяжелый.
ADOTable нет и в помине. Пользуюсь ADOQuery, собсно вот:
и далее:
Это всё не от хорошей жизни. Вынужден перебирать каждую строку записи в огромной таблице, ибо не знаю заранее её логического значения. Может использовать поле с нумерованными строками? Но ведь перебор все равно не исчезнет. Да ладно с ним, с перебором, можно подождать. Мне надо выйти быстро на нужный номер записи, а вот это самое проблематичное... ![]() Экземпляр проги только один - у меня. Ни у кого более его не будет. За ссылку спасибо, почитаю.. ![]() |
||||
|
|||||
skyboy |
|
|||
неОпытный ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9820 Регистрация: 18.5.2006 Где: Днепропетровск Репутация: нет Всего: 260 |
budg, пойми, когда у тебя в файле(чем и является база данных) размер блока(строка в отношениий структуры базы данных) нефиксирован, то при переходе от одной строки к другой надо постоячнно искать конец текущей блока, потом - конец следующего и т.д., т.к. бессмыслено работать как с массивом: <offset>=<counter>*<record_size> - ведь резмер записи не одинаков. А когда ты объявишь индекс, то доступ к строке с нужным тебе индексом(использование автоинкремента и даст тебе номер строки) буде облегчен - ядро будет "в курсе", что строка с индексом 5(5 строка!) находится в файле по смещению 200 байт, а строка с индексом 50 - по смещению в 1012354 байта. При этом не надо будет перебирать данные в поисках признака конца строки - смещения будут заданы явно. Конечно, если у тебя была удалена запись с индексом 42, а последняя строка имеет автоинкрементый индекс 2201, то никто не "заполнит" пустую позицию с номером-индексом 42, но ведь ты при проверке можешь удостовериться, что требуемая запись существует, правда ведь? ;) Так что с индексом намного проще и быстрее..
|
|||
|
||||
Vit |
|
|||
![]() Vitaly Nevzorov ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 10964 Регистрация: 25.3.2002 Где: Chicago Репутация: 14 Всего: 207 |
Так... ставим с головы на ноги... 1. В чём логика проверки каждой строки? Опиши пожалуйста, возможно что это можно сделать одним запросом, если нет, то это надо писать на T-SQL курсорами, это даст выигрышь в производительности примерно 2-3 порядка в самом плохом случае, в хорошем - на 5-6 порядков. 2. Нумеровать строки надо обязательно! 3. Тот запрос что вы привели делать не в коем случае нельзя если таблица больше 1000 записей, убьете не только сервак но и сетку. 4. MoveTo использовать не желательно. Используйте запрос строки по её номеру который проиндексирован... А вообще желательно описать здесь конкретно задачу, мы помозгуем вместе. Я уже года 2 как занимаюсь тем что переписываю такие вот ужастики в нормальный вид, и то что работало неделю почему-то начинает работать по 10 минут.... Скорее всего вы просто не с правильного конца решаете задачу, это очень частая проблема, особенно для тех кто только что перешел с локальных баз данных или вообще только начал работать с базами данных. Сервера могут работать по логике которую вы пытаетесь создать, но как правило это даёт примерно такой-же эффект как использование микроскопа для забивания гвоздей, гвозди забиваются но очень криво и замена окуляра помогает незначительно... -------------------- With the best wishes, Vit I have done so much with so little for so long that I am now qualified to do anything with nothing Самый большой Delphi FAQ на русском языке здесь: www.drkb.ru |
|||
|
||||
budg |
|
|||
Новичок Профиль Группа: Участник Сообщений: 16 Регистрация: 21.12.2005 Репутация: нет Всего: нет |
Задача, собственно, в следующем...
Есть в базе две таблицы (вполне большого размера). Назовем их условно А и В. Таблица В подчинена таблице А по ринципу "один ко многим", т.е. одной строке таблицы А соответствует множество строк таблицы В ( от одной до нескольких сотен). Программист который создавал базу, построил связь таблиц через код проги клиента по некому полю ID . При удалении строки в табл. А, должны были удаляться строки в талице В. Все просто. Однако, он то ли забыл, то ли была еще какая задумка, но удаление строк в таблице В не реализовано. Удаляется только строка в табл. А. Строки в табл. В с данным значением индексного поля "подвисают". Хуже всего, что при создании новых записей, возможно пересечение значений индексных полей с "подвисшими" записями, что приводит к появлению ложной информации. Периодически это проявлялось. Впрочем, это можно рассматривать как "фичу", поскольку удается восстановить случайно удаленные данные(пользователи все равно удаляют, несмотря на предупреждения). Хотя это немного трудоемко. Для очистки таблицы от таких "подвисших" записей написал небольшую прогу. Все получилось неплохо, кроме одного - сканирования таблицы и перехода к нужной записи. Проверять приходиться каждую строку в табл. В на предмет наличия заголовка в табл. А. Отсюда все проблемы. Если подскажете, буду премного благодарен... ![]() Это сообщение отредактировал(а) budg - 22.5.2006, 09:26 |
|||
|
||||
TheCetus |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 134 Регистрация: 9.3.2006 Репутация: нет Всего: 2 |
Судя по описанию все 'очистки' можно сделать одним SQL запросом...
опиши подробнее критерий удаления подвисших записей |
|||
|
||||
budg |
|
|||
Новичок Профиль Группа: Участник Сообщений: 16 Регистрация: 21.12.2005 Репутация: нет Всего: нет |
можно одним запросом - это точно... А критерий очень простой - - текущая строка - если значения поля ID из табл. В нет в столбце ID табл. А - зачит удаляем (или заносим в список для удаления). - след строка Впрочем, пытаюсь создать некий программный инструмент не только для удаления, но и восстановления данных |
|||
|
||||
Vit |
|
||||||
![]() Vitaly Nevzorov ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 10964 Регистрация: 25.3.2002 Где: Chicago Репутация: 14 Всего: 207 |
Ну обычный outer join даёт тебе список строк которые не прилинкованы. Что с ними делать?
1) Или удалить:
2) Или перенести в новую таблицу и там с ними разбираться:
3) Или создать для них корреспондентные записи в мастер таблице:
После этого задать внешний ключ с каскадным удалением... Не вижу никакой необходимости ни в программах, ни в построчном проходе -------------------- With the best wishes, Vit I have done so much with so little for so long that I am now qualified to do anything with nothing Самый большой Delphi FAQ на русском языке здесь: www.drkb.ru |
||||||
|
|||||||
budg |
|
|||
Новичок Профиль Группа: Участник Сообщений: 16 Регистрация: 21.12.2005 Репутация: нет Всего: нет |
Спасибо.
Буду разбираться. |
|||
|
||||
Vit |
|
|||
![]() Vitaly Nevzorov ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 10964 Регистрация: 25.3.2002 Где: Chicago Репутация: 14 Всего: 207 |
Ну спрашивай если чего... пока твоя задача из раздела когда никаких пошаговых проходов вроде не нужно, как и клиентских програм... Я таких случаев много поисправлял, Query Analyser практически единственное что нужно, да немного анализа что творится, а исправляется всё это несколькими запросами. Но даже если и нужен проход по записям, то и он организуется без всякой программы, прямо в Query Analyser при щпомощи курсоров, будет на 2-3 порядка медленнее чем запросом, но на много порядков быстрее чем с помощью клиентского приложения.
-------------------- With the best wishes, Vit I have done so much with so little for so long that I am now qualified to do anything with nothing Самый большой Delphi FAQ на русском языке здесь: www.drkb.ru |
|||
|
||||
![]() ![]() ![]() |
Правила форума "Delphi: Базы данных и репортинг" | |
|
Запрещено: 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами Обязательно указание: 1. Базы данных (Paradox, Oracle и т.п.) 2. Способа доступа (ADO, BDE и т.д.)
FAQ раздела лежит здесь! Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Vit, Петрович. |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Delphi: Базы данных и репортинг | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |