Эффективно ли использовать реляционные операторы для даты или целочисленных значений, хранящихся в столбце char на сервере ms sql? - PullRequest
4 голосов
/ 06 января 2020

Я в разработке 5 лет. Но это выглядит совершенно новым для меня. Недавно я работаю над приложением Legacy, где значения date и integer хранятся в столбце CHAR в ms sql server. И шокирующая вещь (по крайней мере, для меня, потому что я никогда раньше не думал об этом) заключается в том, что реляционные операторы работают с date значениями, хранящимися в столбце CHAR.

Боюсь, что это будет иметь проблему с производительностью. Это правильно или я не прав? Любое неявное приведение или преобразование произойдет в ms sql server перед применением операторов отношений? Или это нормально делать в ms sql server?

Мы планируем перенести это и хотим проверить, могу ли я продолжить эту настройку или нужно date сохранить в столбце типа DATE и integer в столбце типа int в ms sql server?

Я также отметил, что все даты хранятся в виде строки в формате "ГГГГ / ММ / ДД" в таблице.

Вот тестовая таблица которые я создал и протестировал.

CREATE TABLE [dbo].[TestTable](
    [Date] [char](10) NULL,
    [Integer] [char](10) NULL
) ON [PRIMARY]
GO

SELECT * FROM TESTTABLE

enter image description here

SELECT * FROM TESTTABLE where [Date] > '1993/02/10'

enter image description here

Пожалуйста посоветуйте.

Ответы [ 3 ]

7 голосов
/ 06 января 2020

Не хранить даты в виде строк. Вместо этого используйте соответствующий date -подобный тип данных.

Хотя строковый формат, такой как YYYY/MM/DD, позволяет выполнять сравнения и сортировку по равенству и неравенству, появляются другие ограничения, например:

  • манипуляции с датами, например, добавление или вычитание интервалов, утомительны для строк
  • Невозможно обеспечить целостность данных (как убедиться, что ваша строка является допустимой датой?)

Чтобы обойти это, вы скоро найдете в запросах преобразование строк в даты, что крайне неэффективно.

4 голосов
/ 06 января 2020

Лучше хранить значения, используя правильные типы данных.

Однако, если даты сохраняются в формате ГГГГММДД - последовательно - тогда операции сравнения и упорядочения работают нормально. То есть сравнения в виде строк такие же, как сравнения в датах .

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

Если это работающие унаследованные приложения, просто запланируйте исправление при замене приложения.

3 голосов
/ 06 января 2020

Я думаю, что у вас будет больше проблем с преобразованием дат из разных форматов, чем с производительностью.

Допустим, ваша система (или некоторые из ваших систем) решили отправить что-то вроде ' 1993-02-10 ', вам придется "обработать" эту новую строку, потому что она никогда не будет соответствовать вашим запросам.

Возвращаясь к проблемам кода и производительности, я сделал этот быстрый пример, чтобы посмотрим, сможем ли мы поймать стоимость «неявного приведения», но это кажется презренным (см. CONVERT_IMPLICIT в конце плана запроса?):

-- Create a temp table to test
CREATE TABLE #TestTable (
    [Date] [char](10) NULL,
    [Integer] [char](10) NULL
)

-- And an index to search for [Integer]
CREATE INDEX Idx_Integer ON #TestTable ([Integer]);

// Create some data
INSERT INTO #TestTable( [Date], [Integer] ) VALUES('2019/01/01', 1)
INSERT INTO #TestTable( [Date], [Integer] ) VALUES('2019/02/01', 2)
INSERT INTO #TestTable( [Date], [Integer] ) VALUES('2019/03/01', 3)
INSERT INTO #TestTable( [Date], [Integer] ) VALUES('2019/04/01', 4)
INSERT INTO #TestTable( [Date], [Integer] ) VALUES('2019/05/01', 5)
GO 100000

// And a unique record so SQL uses the index
INSERT INTO #TestTable( [Date], [Integer] ) VALUES('2019/05/01', 7)

// Select with Query-Plan (Ctrl+M)
SELECT      [Integer]
    FROM #TestTable
    WHERE   [Integer] = 7

DROP TABLE #TestTable;

enter image description here

VS:

enter image description here

Удачного кодирования!

...