Я занимаюсь разработкой приложения на Ruby on Rails с базой данных PostgreSQL (9.4). Для моего варианта использования столбцы в таблицах будут просматриваться очень часто, поскольку весь смысл приложения заключается в поиске очень специфических атрибутов в модели.
В настоящее время я решаю, использовать ли integer
тип или просто использовать типичный строковый тип (например character varying(255)
, по умолчанию в Rails ) для столбцов, так как я не уверен, какая разница в производительности будет в индексе.
Эти столбцы являются перечислениями . Они имеют фиксированный размер для количества возможных значений, которые они могут иметь. Большинство значений enum не превышают 5, что означает, что индекс будет более или менее фиксированным на протяжении всего жизненного цикла приложения ; таким образом, целочисленные и строковые индексы будут одинаковыми по количеству узлов.
Тем не менее, строка, которая будет проиндексирована, может иметь длину около 20 символов, что в памяти примерно в 5 раз больше целого числа (если целое число равно 4 байта, и строки являются чистым ASCII с 1 байтом на символ, то это верно). Я не знаю, как движки баз данных выполняют поиск по индексу, но если ему нужно «сканировать» строку, пока она не совпадет в точности , то по сути это означает, что поиск строки будет в 5 раз медленнее, чем поиск целых чисел; «сканирование» до совпадения для целочисленного поиска будет 4 байта вместо 20. Вот что я представляю:
Значение поиска (целое число) 4:
сканирование ............................ НАЙДЕНО | получение записей ... | BYTE_1 | BYTE_2 | BYTE_3 | BYTE_4 | BYTE_5 | BYTE_6 | BYTE_7 | BYTE_8 | ... |
Значение поиска (строка) "some_val" (8 байт):
Сканирование ................................................. .................................... НАЙДЕНО | получение записей ... | BYTE_1 | BYTE_2 | BYTE_3 | BYTE_4 | BYTE_5 | BYTE_6 | BYTE_7 | BYTE_8 | ... |
Я надеюсь, что это имеет смысл. По сути, поскольку целое число занимает меньше места, его можно «сопоставить» быстрее, чем его строковый аналог. Возможно, это совершенно неверное предположение, но я не эксперт, поэтому я и спрашиваю вас, ребята! Я полагаю, что этот ответ, который я только что нашел, кажется, подтверждает мою гипотезу, но я хочу быть уверенным.
Число возможных значений в столбце не изменится при использовании любого из них, поэтому сам индекс не изменится (если я не добавлю новое значение в перечисление). В этом случае будет ли разница в производительности при использовании integer
или varchar(255)
, или имеет ли смысл использовать целочисленный тип?
Причина, по которой я спрашиваю, состоит в том, что enum
тип Rails отображает целые числа в строковые ключи, но они не предназначены для столбцов, ориентированных на пользователя. По сути, вы не можете сделать проверку, что значение перечисления является допустимым, потому что недопустимое значение вызовет ArgumentError
перед выполнением любых проверок . Использование string
типа позволило бы провести валидацию, но если бы это повлияло на производительность, я бы лучше решил проблему с валидацией.
varchar(255)
сравнения, напримерvarchar(260)
. В SQL Server 6.x могло быть что-то подобное, но долгое время это не было так.