Скорость SQL SELECT int vs varchar

110

Я создаю таблицу, и это заставило меня задуматься.

Если я сохраню, скажем, автомобили, у которых есть марка (например, BMW, Audi и т. Д.), Будет ли это иметь значение для скорости запроса, если я сохраню марку как int или varchar.

Так это

SELECT * FROM table WHERE make = 5 AND ...;

Быстрее / медленнее, чем

SELECT * FROM table WHERE make = 'audi' AND ...;

или скорость будет примерно такой же?

googletorp
источник

Ответы:

100

Сравнение Int выполняется быстрее, чем сравнение varchar, по той простой причине, что int занимают гораздо меньше места, чем varchars.

Это верно как для неиндексированного, так и для индексированного доступа. Самый быстрый способ - это индексированный столбец типа int.


Как я вижу, вы отметили вопрос как postgreql, возможно, вас заинтересует использование пространства для разных типов даты:

Роберт Мунтяну
источник
13
Вы имеете в виду стр. 7.4. В современных версиях они занимают 1 байт + длина, если у вас <126 байт. Также обратите внимание, что причина, по которой строки намного медленнее, часто заключается в том, что сравнение с учетом сопоставления чрезвычайно дорого, а не потому, что строка занимает больше места. Но конечный результат, конечно же, тот же.
Магнус Хагандер
@Magnus - спасибо за предупреждение. Не стесняйтесь редактировать мой ответ, поскольку я вижу, что у вас достаточно очков репутации.
Роберт Мунтяну
"не то, чтобы строка занимает больше места" ... строки символов сверх минимального размера занимают намного больше места, чем даже числа с высокой точностью, потому что число (единственное число) имеет фиксированную единицу, строки всегда являются агрегатными типами . 8 байтов для 64-битного числа 4 байта на символ в строке, включая либо байт длины, либо структуру; или другой терминатор для невероятно наивных реализаций ...
MrMesees
@RobertMunteanu Привет, Роберт, извиняюсь, я знаю, что это старый пост, но могу ли я проверить… на следующее: чтобы запрашивать целые числа, мне нужно связать каждый строковый столбец с другой таблицей (отношения). однако это означает, что для каждого запроса требуется больше операций соединения. Как определить, стоит ли этого компромисса? Спасибо!
AiRiFiEd
2
«Сравнение Int выполняется быстрее, чем сравнение varchar, из-за того простого факта, что int занимают гораздо меньше места, чем varchars» - в целом это НЕ верно . В зависимости от СУБД, которую вы используете, и конкретных типов данных и строк, которые вы хотите вставить, может оказаться, что ваши (скажем) 8-байтовые целые числа длиннее, чем ascii varchars, содержащие некоторые текстовые идентификаторы средней длины 3-4 символа. Итак, этот ответ - неточный и не имеющий какого-либо конкретного контекста или экспериментальных результатов - на самом деле не отвечает на вопрос. Всем известно , что VARCHARS которые позволили занять гораздо больше места , чем Интс, но они не должны.
Марцин Войнарски
37

Некоторые приблизительные тесты:

4 миллиона записей в Postgres 9.x

Table A = base table with some columns
Table B = Table A + extra column id of type bigint with random numbers
Table C = Table A + extra column id of type text with random 16-char ASCII strings

Результаты на 8GB RAM, i7, SSD ноутбук:

Size on disk:                A=261MB        B=292MB        C=322MB
Non-indexed by id: select count(*), select by id: 450ms same on all tables
Insert* one row per TX:       B=9ms/record        C=9ms/record
Bulk insert* in single TX:    B=140usec/record    C=180usec/record
Indexed by id, select by id:  B=about 200us       C=about 200us

* inserts to the table already containing 4M records

поэтому похоже, что для этой настройки, пока ваши индексы помещаются в ОЗУ, bigint против текста с 16 символами не имеет значения в скорости.

Гжегож Лучиво
источник
6
Очень интересно. Почему разница незначительна?
Chibueze Opata
18

Это будет немного быстрее, используя int вместо varchar. Более важным для скорости является наличие индекса в поле, которое запрос может использовать для поиска записей.

Есть еще одна причина использовать int, и это для нормализации базы данных. Вместо того чтобы хранить в таблице тысячи раз текст Mercedes-Benz, вы должны сохранить его идентификатор, а название бренда - один раз в отдельной таблице.

Guffa
источник
Не могли бы вы объяснить больше? Вы имеете в виду вместо того, Mercedes-Benzчтобы хранить тысячи раз id 1. Например таблица car_brands, столбцы Brandsи Id. Ряд Mercedes-Benzи 1. И в главном столбце таблицы Brandsи значение 1. А когда SELECT, то сначала Idиз таблицы, car_brandsа потом SELECT Something FROM main_table WHERE Brands = (SELECT Id FROM car_brands WHERE Brands = Mercedes-Benz). Или какой-то другой подход?
Андрис
3
@ user2118559: Да, именно так вы бы это хранили. Для того, чтобы получить данные, как правило , используют объединение , а не подзапроса: select something from main_table c inner join car_brands b on b.Id = c.Brands where b.Brands = 'Mercedes-Benz'.
Guffa
Почему голос против? Если вы не объясните, что вы считаете неправильным, это не улучшит ответ.
Guffa
8

Если говорить о фактической производительности сравнения строк с не-числами с плавающей запятой, то в этом случае любой размер без знака и со знаком не имеет значения. На самом деле размер - это настоящая разница в производительности. Будь то 1 байт + (до 126 байт) по сравнению с 1,2,4 или 8-байтовым сравнением ... очевидно, что non-float меньше, чем строки и float, и, следовательно, более удобны для процессора при сборке.

Сравнение строки со строкой на всех языках происходит медленнее, чем то, что ЦП может сравнить в 1 инструкции. Даже сравнение 8-байтового (64-битного) на 32-битном процессоре все равно быстрее, чем VARCHAR (2) или больше. * Опять же, посмотрите на созданную сборку (даже вручную). Для сравнения char по char требуется больше инструкций, чем от 1 до 8 байтов CPU numeric.

Насколько быстрее? зависит также от объема данных. Если вы просто сравниваете 5 с «audi» - а это все, что есть в вашей БД, результирующая разница настолько минимальна, что вы никогда ее не увидите. В зависимости от ЦП, реализации (клиент / сервер, веб / скрипт и т. Д.) Вы, вероятно, не увидите его, пока не проведете несколько сотен сравнений на сервере БД (возможно, даже пару тысяч сравнений, прежде чем это станет заметным).

  • Чтобы аннулировать некорректный спор о сравнении хешей. Большинство алгоритмов хеширования сами по себе медленные, поэтому вы не получите выгоды от таких вещей, как CRC64 и менее. Более 12 лет я разрабатывал алгоритмы поиска для поисковых систем по нескольким округам и 7 лет для кредитных бюро. Все, что вы можете сохранить в числовом формате, тем быстрее ... например, номера телефонов, почтовые индексы, даже валюта * 1000 (хранение), валюта div 1000 (извлечение) быстрее, чем DECIMAL для сравнений.

Ozz

Озз Никсон
источник
6

Индексирование или нет, int намного быстрее (чем длиннее varchar, тем медленнее он становится).

Другая причина: индекс в поле varchar будет намного больше, чем в int. Для больших таблиц это может означать сотни мегабайт (и тысячи страниц). Это значительно ухудшает производительность, поскольку для чтения одного индекса требуется много операций чтения с диска.

Конрад Гарус
источник
3
Например, из 5 миллионов записей «audi» не будет ли индекс содержать только одну копию строки «audi» и 5 миллионов целых чисел primary_key? Действительно ли разница в размерах будет такой большой, будь то vchar или целое число?
lulalala
Вы правы, lulalala, но для столбца, который будет содержать случайные строки, ответ будет достаточно справедливым.
Awais fiaz
4

В общем, int будет быстрее. Чем длиннее варчар, тем медленнее он работает

Anthares
источник
3

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

Томас Шауб
источник
1
Интересно, как будет разница в скорости между ENUM и int?
googletorp
Есть ли у PostgresSQL enumтип данных? Я думал, что это было конкретно для MySQL.
Роберт Мунтяну
В Postgres есть ENUM, но я не думаю, что он реализован так же, как MySQL. postgresql.org/docs/current/static/datatype-enum.html
googletorp,
2
С точки зрения производительности ENUM должен выполнять более или менее то же самое, что и int в поле поиска, но как varchar в целевом списке (потому что он должен передавать всю строку клиенту для сопоставленных строк, а не только int)
Магнус Хагандер
1
Вот интересное чтение о том, почему НЕ использовать enum в MySQL (просто чтобы подлить масла в огонь: D)
Уилт
1

Если вы включите индексирование по любому из полей, оно будет быстрее. Что касается вашего вопроса, я думаю, что intбыстрее, чем varchar.

Sarfraz
источник
0

В некоторой степени относительный. Да, INT будет быстрее, но вопрос в том, заметно ли это в вашей ситуации. VARCHAR - это просто небольшие слова или более длинные тексты? а сколько строк в таблице? Если есть всего несколько строк, они, скорее всего, будут полностью буферизованы в памяти (при частом запросе), в этом случае вы не заметите большой разницы. Затем, конечно, есть индексация, которая становится более важной, когда таблица растет. Использование SSD может быть быстрее, чем HD с оптимизированными запросами. Также хорошие дисковые контроллеры иногда ускоряют запросы более чем в 10 раз. Это может оставить место для простого использования VARCHAR, что упрощает чтение и запись запросов (нет необходимости писать сложные объединения) и ускоряет разработку. Однако пуристы не согласятся и всегда все нормализуют.

Alex
источник