Производительность сравнения строк и int join в SQL

Принято считать, что поиск в таблице по столбцу int выполняется быстрее, чем по строковому столбцу (скажем, varchar).

Однако, если у меня есть таблица «Рубашки» со столбцом «Цвет», было бы более эффективно создать таблицу «Цвет» с первичным ключом в этой таблице, являющимся внешним ключом в таблице «Рубашки»? Сведет ли объединение на нет преимущество в производительности, связанное с тем, что значение в столбце «Цвет» для «Рубашки» является целым числом, а не строковым значением, таким как «Зеленый», при поиске зеленых рубашек?


person RobertMGlynn    schedule 14.09.2012    source источник
comment
Это реальная проблема с производительностью? Это очень похоже на преждевременную оптимизацию. Поверьте мне: сложные базы данных — это не весело. Не усложняйте базу данных без веской причины.   -  person Brendan Long    schedule 14.09.2012
comment
@BrendanLong Это не реальная проблема с производительностью, а теоретическая. По крайней мере, в моем случае это так. Однако ваш комментарий, кажется, идет вразрез со всеми ответами на нормализацию, данными для теоретического вопроса о производительности.   -  person RobertMGlynn    schedule 15.09.2012
comment
Нормализация является веской причиной для этого, но ваш вопрос касается производительности, поэтому мой комментарий был именно об этом. Теоретическая производительность не является чем-то, о чем стоит беспокоиться.   -  person Brendan Long    schedule 15.09.2012


Ответы (5)


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

Сравнение строк зависит от базы данных, но включает функцию и чтение данных со страницы. Значит, это не бесплатно. Разные базы данных, конечно, могут иметь разные характеристики производительности для строковой функции.

Где он должен храниться, должно быть функцией вашего приложения. Скажем, у вас есть приложение, в котором цвет будет представлен пользователю. Возможно, однажды вы захотите показать название цвета на испанском, суахили или китайском. Если да, то наличие отдельной таблицы значительно упрощает такую ​​интернационализацию. Более прозаично, вы можете захотеть запретить ввод «Грена», если это так, наличие такой таблицы упрощает список выбора.

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

person Gordon Linoff    schedule 14.09.2012

Если я правильно понимаю, вы спрашиваете, какой из этих двух запросов будет быстрее:

SELECT * FROM shirt where color = 'Green'

vs

SELECT shirt.* FROM shirt s INNER JOIN colors c 
       ON s.colorid = c.colorid 
       WHERE c.color = 'Green'

Это немного зависит от базы данных (ну... может быть, во многом в зависимости от того, правильно ли она оптимизируется, что должно быть в большинстве случаев, если не во всех), но поиск в таблице цветов должен быть незначительным, и тогда оставшееся выполнение может использовать целое число значение поиска и должно быть быстрее. Основная часть обработки в конечном итоге будет эквивалентна SELECT * from shirt WHERE colorid=N. Однако я подозреваю, что вы бы не заметили разницы в скорости, если бы таблица не была достаточно большой. Решение, вероятно, должно быть основано на том, какой дизайн имеет наибольший смысл (вероятно, нормализованный).

person Mark Wilkins    schedule 14.09.2012
comment
+1, потому что, хотя он не совсем ответил на мой вопрос, он отлично его прояснил. - person RobertMGlynn; 15.09.2012

Помимо производительности, создание отдельной таблицы цветов делает ваш дизайн более нормализованным. Итак, когда-нибудь в будущем, когда кто-то решит, что «темно-синий» теперь должен называться «темно-синий», вы обновите 1 строку в своей таблице цветов вместо обновления многих строк в таблице «Рубашки».

person Joe Stefanelli    schedule 14.09.2012
comment
Это вполне логично. - person xyres; 09.06.2015

В СУБД есть возможность оптимизировать показатели там, где имеется ограниченное количество значений. Как сказать SQL сделать это, я не знаю. Может разберется.

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

Как указывает Джо, база данных должна быть максимально нормализована. Если у вас есть отдельная функция отчетности, которая может вызвать проблемы с производительностью, вы должны запустить периодическое преобразование (или установить правила для создания в реальном времени) второй схемы только для чтения. Первый — это OLTP, а второй — OLAP («хранилище данных»); это важные концепции, которые необходимо иметь в виду, если вы собираетесь серьезно относиться к своим данным.

Если это достаточно важно знать, проверьте это.

Если никто не дает вам ответа, лучший способ сделать это — проверить самостоятельно.

(1) сделать 2 базы данных

(2) каждый с тестом ваших 2 таблиц

(3) В базе данных просто присоединяется к строке «цвет» и использует ее для FK; другой присоединяется через int ('colorID')

Заполните каждый 2 миллионами фиктивных строк. Запустите несколько запросов для каждого, синхронизируя 1-й запуск и средние запуски.

Используйте экземпляр на своей машине разработки, чтобы вывести сеть из поля зрения.

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

person FastAl    schedule 14.09.2012

На самом деле это зависит от оптимизатора запросов. Ваша таблица цветов будет очень маленькой, поэтому, вероятно, основываясь на статистике базы данных и планах запросов, она, вероятно, будет полностью загружена в память, поэтому вы не только в конечном итоге сведете на нет затраты на соединение, но на самом деле это может быть быстрее. Это, очевидно, зависит от используемой вами СУБД, но некоторые СУБД могут принимать подсказки о том, как обращаться с таблицей особым образом.

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

person Carlos Grappa    schedule 14.09.2012