Тип данных при поиске в базе данных


3 0

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

Не все еще перешли на Unicode и некоторые до сих пор используют varchar, хотя давно уже пора перейти на nvarchar. Проблема в том, что Dapper в качестве строк использует как раз nvarchar, а Transact-SQL оказывается не очень дружит с преобразованиями строк.

Допустим, что у вас есть таблица и поле Firstname типа varchar. Если таблица большая, достаточно даже миллиона строк, и SQL сервер может упасть даже под небольшим натиском простого запроса:

Declare @s nvarchar  
Set @s = 'test' 
 
Select * from Table where Firstname = @s 

Даже при наличии индекса этот запрос может выполнятся непредсказуемым образом. При выполнении обновления строки план выполнения у меня показал, что сервер будет делать скан индекса по Email, и только потом полезет в индекс по имени. Я был реально в шоке, когда я это увидел.

Проблема решается просто - нельзя использовать nvarchar строки, если поле простой varchar и если модифицировать запрос так, то он выполняется быстро и использует индексы правильно:

Declare @s nvarchar  
Set @s = 'test' 
 
Select * from Table where Firstname = cast(@s as varchar) 

Всего лишь банальное приведение строки позволяет вернуть план выполнения запроса к разумному. А ведь оптимизатор запросов SQL Server может сделать это преобразование сам. Ведь когда сравнивается две строки, есть два решения - преобразовать искомое значение к типу поля или преобразовывает все значения в таблице к искомому. Какой выбрал путь SQL Server - я понятия не имею.

Я в основном пишу сайты для американцев и до сих пор использую varchar (не мое решение), поэтому на эту проблему производительности как-то не натыкался. Но тем, кто работает с SQL Server - будьте осторожны. Создавайте параметры именно того типа, который вам нужен, помните, что varchar и nvarchar хоть и взаимозаменяемые, но с точки зрения производительности замену лучше не делать.

Проблема еще в том, что строка string в .NET мапится сразу на оба типа строк базы данных. Если же нужно явно указать принадлежность к varchar (не юникод), нужно использовать AnsiString

Более очевидная проблема может быть с конфликтом строки и числа.

Declare @s int
Set @s = 111
 
Select * from Table where FieldName = @s 

Такой запрос абсолютно легален, если в поле FieldName только числа, то запрос будет выполнен, даже если тип поля строковй, но только он будет на много медленней, чем если объявить переменную как строку. Тип строки и тип параметра должны четко совпадать, иначе это сильно бъет по производительности системы.


Понравилось? Кликни Лайк, чтобы я знал, какой контент более интересен читателям. Заметку пока еще никто не лайкал и ты можешь быть первым


Комментарии

iAlex

28 Февраля 2014

да, я отаком и неподозревал


Kastor

28 Февраля 2014

На счет последнего примера:


Declare @s int
Set @s = 111

Select * from Table where FieldName = @s

Такой запрос корректен и выполнится успешно (если FieldName будет содержать только строки из цифр) но не попадет в индекс, если бы он был по столбцу FieldName. Это потому, что в таком запросе значение из FieldName автоматически преобразовывается к числу, с которым идет сравнение. И если мы хотим, что бы такой запрос попадал в индекс, то нужно создавать отдельный индекс на функцию преобразования значений из столбца FieldName в число, а не просто на столбец FieldName.


Михаил Фленов

28 Февраля 2014

но не попадет в индекс,


Наверно не в индекс, а в выборку. Если во время выполнения плана SQL в выборке сервер наткнется на строку, которую не сможет превратить в число, то будет ошибка. В это случае преобразование значений колонки действительно имеет смысл и тут не придраться к логике SQL. В случае с varchar и nvarchar я думаю, что можно было бы преобразовать искомое значение. Но это моя мысль, а разработчикам SQL Server виднее.

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


Добавить Комментарий

Еще что-нибудь

Хотите найти еще что-то интересное почитать? Можно попробовать отфильтровать заметки на блоге по категориям.

О блоге

Программист, автор нескольких книг серии глазами хакера и просто блогер. Интересуюсь безопасностью, хотя хакером себя не считаю

Обратная связь

Без проблем вступаю в неразборчивые разговоры по e-mail. Стараюсь отвечать на письма всех читателей вне зависимости от страны проживания, вероисповедания, на русском или английском языке.

Пишите мне