Является ли LTRIM (RTRIM (COALESCE (TextField, ''))) плохим? - PullRequest
1 голос
/ 20 апреля 2009

У меня таблица с очень большим трафиком с полем char(50), которое участвует в нескольких индексах. Это поле char(50) допускает NULLS, и в этом случае значение NULL считается таким же, как и строка, не равная NULL, для моей цели.

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

У меня есть sproc, который используется для копирования данных из одной таблицы в основную таблицу, и он должен быть высокопроизводительным. Мне нужно удалить дубликаты записей перед вставкой новых данных, и я использую метод, описанный в этой теме , чтобы выполнить удаление.

Мой оператор удаления выглядит так (упрощенно):

delete masterTable
from masterTable t
    join incomingDataTable inc on
    (
        LTRIM(RTRIM(COALESCE(inc.TextField,''))) = 
             LTRIM(RTRIM(COALESCE(t.TextField,'')))
    )
where LTRIM(RTRIM(COALESCE(t.TextField,''))) <> ''  

Я прочитал , что конструкции типа LTRIM (RTRIM (...)) плохие. Может ли мой оператор удаления быть улучшен, и если да, то как?

РЕДАКТИРОВАТЬ: Просто чтобы уточнить, TextField принимает участие в индексах в обеих таблицах. EDIT2: TextField определяется как char(50) в обеих таблицах. Это не тип TEXT.

Ответы [ 6 ]

8 голосов
/ 20 апреля 2009

Вам необходимо:

  1. Создать вычисляемый столбец в masterTable, используя выражение LTRIM(RTRIM(COALESCE(TextField,'')))
    • Создайте индекс по этому столбцу и
    • Используйте этот столбец в соединении.

То, как ваша таблица теперь оформлена, совершенно невозможно сделать этот запрос удобным для индекса.

Если вы не можете изменить структуру таблицы, но можете оценить количество LEADING пробелов, вы можете использовать подход, описанный здесь .

Однако это решение далеко не так эффективно, как создание индекса для вычисляемого столбца.

4 голосов
/ 20 апреля 2009

Это плохо, потому что вашему JOIN придется сканировать весь индекс, потому что ваше состояние не SARGable

Вы также уверены, что это тип данных TEXT? В последний раз я проверял, что вы не можете использовать LTRIM или RTRIM для столбца типа данных Text?

в ответ на комментарий символа против varchar, запустите это

declare @v varchar(50),@v2 char(50)
select @v ='a',@v2 = 'a'

select datalength(@v),datalength(@v2)
3 голосов
/ 20 апреля 2009

Я бы порекомендовал изменить этот тип данных на VARCHAR (50) - примерно до 10 символов, CHAR (x) может иметь смысл, поскольку он немного быстрее и имеет меньше накладных расходов - но с 50 символами, если все столбцы не полностью при использовании до 50 символов это большие накладные расходы, тем более что этот столбец также используется в индексах.

Изменение его на VARCHAR (50), возможно, значительно уменьшит пространство, необходимое для таблицы (в зависимости от объема данных и того, сколько из 50 символов действительно используется), и все задействованные индексы также получат много меньше - плюс вам больше не понадобятся такие вещи COALESCE, LTRIM, RTRIM: -)

Марк

2 голосов
/ 20 апреля 2009

Если вам приходится обрезать данные каждый раз, когда вы их используете, это не должен быть тип char, а тип данных varchar. Каждый раз, когда вам приходится использовать функцию каждый раз, когда вы запрашиваете поле, в вашей базе данных что-то не так.

Вам может пригодиться это обсуждение: Является ли тип данных CHAR в SQL устаревшим? Когда вы его используете?

2 голосов
/ 20 апреля 2009

Я считаю, что SQLMenace правильный.

Как насчет добавления триггера INSERT / UPDATE в таблицу, чтобы гарантировать отсутствие пробелов в этом столбце?

Если столбец VARCHAR, SQL Server автоматически игнорирует завершающий пробел. Ведущий пробел все еще имеет значение.

На самом деле, не будет ли SQL Server автоматически дополнить оба столбца символами CHAR (50) перед выполнением JOIN? (Влияние конверсии.)

2 голосов
/ 20 апреля 2009

Я думаю, что в SQL Server вы можете сопоставить дополненную строку с не дополненной строкой, сэкономив при этом усилия на LTRIM / RTRIM, однако я не 100% на этом ...

Однако приведение в порядок данных является частью ETL и должно быть выполнено до того, как ваши данные попадут туда, куда они направляются. В больших наборах данных вы можете обнаружить, что быстрее создать временную копию данных, обработать их, проиндексировать, а затем выполнить необходимое сопоставление.

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