Лучшая методика самостоятельного соединения при проверке дубликатов - PullRequest
8 голосов
/ 02 мая 2011

Я пытаюсь оптимизировать запрос, который находится в производстве и занимает много времени. Цель состоит в том, чтобы найти дубликаты записей на основе соответствующих критериев значений полей и затем удалить их. Текущий запрос использует самостоятельное соединение через внутреннее соединение для t1.col1 = t2.col1, а затем предложение where для проверки значений.

select * from table t1 
inner join table t2 on t1.col1 = t2.col1
where t1.col2 = t2.col2 ...

Что может быть лучше для этого? Или все таки по индексам? Может быть,

select * from table t1, table t2
where t1.col1 = t2.col1, t2.col2 = t2.col2 ...

в этой таблице более 100 миллионов строк.

MS SQL, SQL Server 2008 Enterprise

select distinct t2.id
    from table1 t1 with (nolock)
    inner join table1 t2 with (nolock) on  t1.ckid=t2.ckid
    left join table2 t3 on t1.cid = t3.cid and t1.typeid = t3.typeid
    where 
    t2.id > @Max_id and
    t2.timestamp > t1.timestamp and
    t2.rid = 2 and
    isnull(t1.col1,'') = isnull(t2.col1,'') and 
    isnull(t1.cid,-1) = isnull(t2.cid,-1) and
    isnull(t1.rid,-1) = isnull(t2.rid,-1)and 
    isnull(t1.typeid,-1) = isnull(t2.typeid,-1) and
    isnull(t1.cktypeid,-1) = isnull(t2.cktypeid,-1) and
    isnull(t1.oid,'') = isnull(t2.oid,'') and
    isnull(t1.stypeid,-1) = isnull(t2.stypeid,-1)  

    and (
            (
                t3.uniqueoid = 1
            )
            or
            (
                t3.uniqueoid is null and 
                isnull(t1.col1,'') = isnull(t2.col1,'') and 
                isnull(t1.col2,'') = isnull(t2.col2,'') and
                isnull(t1.rdid,-1) = isnull(t2.rdid,-1) and 
                isnull(t1.stid,-1) = isnull(t2.stid,-1) and
                isnull(t1.huaid,-1) = isnull(t2.huaid,-1) and
                isnull(t1.lpid,-1) = isnull(t2.lpid,-1) and
                isnull(t1.col3,-1) = isnull(t2.col3,-1) 
            )
    )

Ответы [ 6 ]

13 голосов
/ 02 мая 2011

Почему я присоединяюсь: это совокупный вопрос.

Надеюсь, у вас есть индекс col1, col2, ...

--DELETE table
--WHERE KeyCol NOT IN (
select
    MIN(KeyCol) AS RowToKeep,
    col1, col2, 
from
    table
GROUP BY
    col12, col2
HAVING
   COUNT(*) > 1
--)

Однако, это займет некоторое время. посмотрите на методы массового удаления

1 голос
/ 02 мая 2011

Для таблицы с 100m + строками оптимизируется использование функций GROUPBY и использование таблицы удержания.Даже при том, что это переводится в четыре запроса.

ШАГ 1: создайте удерживающий ключ:

SELECT col1, col2, col3=count(*)
INTO holdkey
FROM t1
GROUP BY col1, col2
HAVING count(*) > 1

ШАГ 2: Вставьте все дублирующиеся записи вholddups.Это необходимо для шага 4.

SELECT DISTINCT t1.*
INTO holddups
FROM t1, holdkey
WHERE t1.col1 = holdkey.col1
AND t1.col2 = holdkey.col2

ШАГ 3: Удалить дублирующиеся строки из исходной таблицы.

DELETE t1
FROM t1, holdkey
WHERE t1.col1 = holdkey.col1
AND t1.col2 = holdkey.col2

ШАГ4: Поместите уникальные строки обратно в исходную таблицу.Например:

INSERT t1 SELECT * FROM holddups
1 голос
/ 02 мая 2011

Два метода, которые вы даете, должны быть эквивалентны. Я думаю, что большинство SQL-движков в обоих случаях делали бы одно и то же.

И, кстати, это не сработает. У вас должно быть хотя бы одно поле, которое отличается от другого, или каждая запись будет соответствовать сама себе.

Возможно, вы захотите попробовать что-то более похожее на:

select col1, col2, col3
from table
group by col1, col2, col3
having count(*)>1
1 голос
/ 02 мая 2011

Вы можете использовать ROW_NUMBER (), чтобы найти повторяющиеся строки в одной таблице.

Вы можете проверить здесь

0 голосов
/ 18 января 2013

По моему опыту, производительность SQL Server действительно плоха при OR условиях. Вероятно, это не само соединение, а с таблицей 3, что приводит к плохой производительности. Но, не видя плана, я не был бы уверен.

В этом случае это может помочь разделить ваш запрос на две части: Один с условием WHERE t3.uniqueoid = 1 и другой с условием WHERE для других условий таблицы3, а затем используйте UNION ALL для добавления одного к другому.

0 голосов
/ 02 мая 2011

Чтобы обнаружить дубликаты, вам не нужно присоединяться:

SELECT col1, col2
FROM table
GROUP BY col1, col2
HAVING COUNT(*) > 1

Это должно быть намного быстрее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...