Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Sybase ASA, ASE, IQ [игнор отключен] [закрыт для гостей] / Оптимизация обработки дубликатов / 7 сообщений из 7, страница 1 из 1
04.07.2007, 07:48
    #34636644
Slaven
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация обработки дубликатов
В таблице table дубликатом считается запись, в которой совокупность значений полей 1,2,3 идентичны соответствующим значениям другой записи.
Поставлена задача удалить дубликаты из таблицы, обновив при этом ссылки из таблицы table2 на id единственной оставшейся записи table.
СУБД SA10, UI - С#.NET
Пошел таким путем:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
//Выбираю записи, для которых есть дубликаты
query = database.Select("select t.1,t.2,t.3 from (SELECT count(*) c,1,2,3 FROM table group by 1,2,3 t where c>1");
while (query.Read())
{
 //нахожу все дубликаты для соответствующей записи
 query2 = database.Select("SELECT ID FROM table WHERE 1='" + query[0].ToString() + "' AND 2='" + query[1].ToString() + "' AND 3='" + query[2].ToString() + "'");
 query2.Read();
 //id единственной остающейся записи
 String verId = query2[ 0 ].ToString();
 // перечень удаляемых id
 String delId = "";
 while (query2.Read())
 {
    delId += query2[ 0 ].ToString() + ",";
 }
 delId = delId.Substring( 0 , delId.Length -  1 );
 query2.Close();
 //обновляю ссылки в ссылочной таблице
 database.Update("UPDATE table2 SET col_ID="+verId+" WHERE col_ID IN ("+delId+")");
 //удаляю записи-дубликаты
 database.Update("DELETE FROM table WHERE ID IN ("+delId+")");
}
query.Close();

Эффективно, но с учетом того что в Table 3млн. записей жутко долго. Причем, естесственно update и delete выполняются моментом, а вот select id для каждого дубликата жутко долгий (около 0,8 сек каждый select).
Буду благодарен за любой подсказанный способ оптимизации алгоритма
...
Рейтинг: 0 / 0
04.07.2007, 08:16
    #34636668
Рыжий Кот
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация обработки дубликатов
нужно вывести все дублирующиеся, отсортировав по t.1, t.2, t.3
а потом пробежать по ним сверяя на равенство текущего с последующим...
это позволит избежать многократных селектов
...
Рейтинг: 0 / 0
04.07.2007, 09:34
    #34636787
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация обработки дубликатов
Можно создать кластерный индекс с параметром IGNORE_DUP_KEY по этим полям. Тогда лишние записи "уберутся" сами в процессе создания индекса. Только это не решит проблему перессылания записей со старых на новые. Это можно сделать, создав таблицу соответствия
набора этих уникальных полей, старого идентификатора и нового идентификатора. Она заполняется ДО удаления дупликатов, потом в нее проставляется новый ключ из оставшихся записей, у которых набор полей такой же, ну и потом можно восстановить ссылки во всех таблицах. На время операции FK на эту таблицу надо естественно убрать, потом восстановить.
...
Рейтинг: 0 / 0
04.07.2007, 14:41
    #34638154
DimM256
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация обработки дубликатов
Серег, дай поля и таблицы я те запрос минуты за 3 напишу ).

Вопрос решается 2 запросами, сначало update потом delete.

1. сначало update тупо в Таблице2 проапдейтить все по max(с таблицы 1) а потом удалить все из таблицы 1 где не сджойнится с таблицей 2
...
Рейтинг: 0 / 0
04.07.2007, 14:48
    #34638195
DimM256
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация обработки дубликатов
//Выбираю записи, для которых есть дубликаты
query = database.Select("select t.1,t.2,t.3 from (SELECT count(*) c,1,2,3 FROM table group by 1,2,3 t where c>1");
while (query.Read())
{
//нахожу все дубликаты для соответствующей записи
query2 = database.Select("SELECT ID FROM table WHERE 1='" + query[0].ToString() + "' AND 2='" + query[1].ToString() + "' AND 3='" + query[2].ToString() + "'");
query2.Read();
//id единственной остающейся записи
String verId = query2[0].ToString();
// перечень удаляемых id
String delId = "";
while (query2.Read())
{
delId += query2[0].ToString() + ",";
}
delId = delId.Substring(0, delId.Length - 1);
query2.Close();
//обновляю ссылки в ссылочной таблице
database.Update("UPDATE table2 SET col_ID="+verId+" WHERE col_ID IN ("+delId+")");
//удаляю записи-дубликаты
database.Update("DELETE FROM table WHERE ID IN ("+delId+")");
}
query.Close();

Это п....ц - срочно звоню твоему нчальнику )))))
...
Рейтинг: 0 / 0
05.07.2007, 15:04
    #34641260
Slaven
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация обработки дубликатов
Димас, на самом деле сразу сделать update и delete не получицо, т.к. на запись может не быть ссылок, а она будет дублироваться в Table1 все равно, к тому же я указал в примере 1 ссылочную таблицу а у меня их на самом деле штук 10, и возможна такая ситуация, когда не в 1 из них не будет ссылки на интрересующую меня запись-дубликат
...
Рейтинг: 0 / 0
05.07.2007, 18:23
    #34642150
White Owl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оптимизация обработки дубликатов
SlavenДимас, на самом деле сразу сделать update и delete не получицо, т.к. на запись может не быть ссылок, а она будет дублироваться в Table1 все равно, к тому же я указал в примере 1 ссылочную таблицу а у меня их на самом деле штук 10, и возможна такая ситуация, когда не в 1 из них не будет ссылки на интрересующую меня запись-дубликатА при чем здесь ссылки? Или под ссылками имеются в виду внешние ключи симулируемые клиентским приложением?
Вообще-то, чтобы такая ситуация не возникала, поля f1,f2,f3 для таблицы надо было объявить первичным ключом. Но если таблица досталась в наследство, ее нужно срочно исправлять.
...
Рейтинг: 0 / 0
Форумы / Sybase ASA, ASE, IQ [игнор отключен] [закрыт для гостей] / Оптимизация обработки дубликатов / 7 сообщений из 7, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]