Каковы варианты использования для выбора CHAR по VARCHAR в SQL?

Что такое NullPointerException?

Хорошим местом для начала является JavaDocs . Они охватывают это:

Брошено, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:

  • Вызов метода экземпляра нулевого объекта.
  • Доступ или изменение поля нулевого объекта.
  • Выполнение длины null, как если бы это был массив.
  • Доступ или изменение слотов с нулевым значением, как если бы это был массив.
  • Бросать нуль, как если бы это было значение Throwable.

Приложения должны бросать экземпляры этого класса для указания других незаконных видов использования нулевого объекта.

blockquote>

Также, если вы попытаетесь использовать нулевую ссылку с synchronized, который также выдаст это исключение, за JLS :

SynchronizedStatement:
    synchronized ( Expression ) Block
  • В противном случае, если значение выражения равно null, NullPointerException.
blockquote>

Как это исправить?

Итак, у вас есть NullPointerException. Как вы это исправите? Возьмем простой пример, который выдает NullPointerException:

public class Printer {
    private String name;

    public void setName(String name) {
        this.name = name;
    }

    public void print() {
        printString(name);
    }

    private void printString(String s) {
        System.out.println(s + " (" + s.length() + ")");
    }

    public static void main(String[] args) {
        Printer printer = new Printer();
        printer.print();
    }
}

Идентифицирует нулевые значения

. Первый шаг - точно определить , значения которого вызывают исключение . Для этого нам нужно выполнить некоторую отладку. Важно научиться читать stacktrace . Это покажет вам, где было выбрано исключение:

Exception in thread "main" java.lang.NullPointerException
    at Printer.printString(Printer.java:13)
    at Printer.print(Printer.java:9)
    at Printer.main(Printer.java:19)

Здесь мы видим, что исключение выбрано в строке 13 (в методе printString). Посмотрите на строку и проверьте, какие значения равны нулю, добавив протоколирующие операторы или используя отладчик . Мы обнаруживаем, что s имеет значение null, а вызов метода length на него вызывает исключение. Мы видим, что программа перестает бросать исключение, когда s.length() удаляется из метода.

Трассировка, где эти значения взяты из

Затем проверьте, откуда это значение. Следуя вызовам метода, мы видим, что s передается с printString(name) в методе print(), а this.name - null.

Трассировка, где эти значения должны быть установлены

Где установлен this.name? В методе setName(String). С некоторой дополнительной отладкой мы видим, что этот метод вообще не вызывается. Если этот метод был вызван, обязательно проверьте порядок , что эти методы вызывают, а метод set не будет называться после методом печати. ​​

Этого достаточно, чтобы дать нам решение: добавить вызов printer.setName() перед вызовом printer.print().

Другие исправления

Переменная может иметь значение по умолчанию setName может помешать ему установить значение null):

private String name = "";

Либо метод print, либо printString может проверить значение null например:

printString((name == null) ? "" : name);

Или вы можете создать класс, чтобы name всегда имел ненулевое значение :

public class Printer {
    private final String name;

    public Printer(String name) {
        this.name = Objects.requireNonNull(name);
    }

    public void print() {
        printString(name);
    }

    private void printString(String s) {
        System.out.println(s + " (" + s.length() + ")");
    }

    public static void main(String[] args) {
        Printer printer = new Printer("123");
        printer.print();
    }
}

См. также:

Я все еще не могу найти проблему

Если вы попытались отладить проблему и до сих пор не имеете решения, вы можете отправить вопрос для получения дополнительной справки, но не забудьте включить то, что вы пробовали до сих пор. Как минимум, включите stacktrace в вопрос и отметьте важные номера строк в коде. Также попробуйте сначала упростить код (см. SSCCE ).

269
задан Machavity 13 April 2018 в 08:29
поделиться

15 ответов

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

Это варьируется реализацией DB, но обычно VARCHAR использует один или еще два байта устройства хранения данных (для длины или завершения) в дополнение к фактическим данным. Таким образом (принимающий Вы используете набор однобайтового символа), хранение слова "FooBar"

  • CHAR (6) = 6 байтов (никакие издержки)
  • VARCHAR (10) = 8 байтов (2 байта издержек)
  • CHAR (10) = 10 байтов (4 байта издержек)

, Нижняя строка , CHAR может быть быстрее , и больше располагает с интервалами эффективный для данных относительно той же длины (в двух различиях в длине символов).

Примечание : Microsoft SQL имеет 2 байта издержек для VARCHAR. Это может варьироваться от DB до DB, но обычно существует по крайней мере 1 байт издержек, должен был указать на длину или EOL на VARCHAR.

, Как был указан Gaven в комментариях при использовании многобайтового набора символов переменной длины как UTF8 тогда CHAR хранит максимальное количество байтов, необходимых для хранения количества символов. Таким образом, если UTF8 будут нужны самое большее 3 байта для хранения символа, то CHAR (6) будет зафиксирован на уровне 18 байтов, даже если только хранение latin1 символы. Таким образом, в этом случае VARCHAR становится намного лучшим выбором.

384
ответ дан Jim McKeeth 23 November 2019 в 02:19
поделиться

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

из-за этого, у Вас нет сбережений пространства при помощи VARCHAR (200) по сравнению с CHAR (200)

0
ответ дан FlySwat 23 November 2019 в 02:19
поделиться

когда использование varchar оценивает потребности SQL Server дополнительные 2 байта за строку для хранения некоторой информации о том столбце, тогда как при использовании символа этому не нужно это поэтому если Вы

1
ответ дан SQLMenace 23 November 2019 в 02:19
поделиться

Я думаю в Вашем случае нет, вероятно, никакой причины не выбрать Varchar. Это дает Вам гибкость и как был упомянут многими респондентами, производительность - такой теперь, когда кроме очень определенных обстоятельств нас meer смертные (в противоположность DBA Google) не заметят различия.

интересной вещью, которую стоит отметить когда дело доходит до Типов БД, является sqlite (популярная мини-база данных с довольно впечатляющей производительностью) помещает все в базу данных как строка и типы на лету.

я всегда использую VarChar и обычно делаю его намного больше, чем я мог бы потребность strickly. Например, 50 для Firstname, поскольку Вы говорите, почему не только быть в безопасности.

2
ответ дан Toby Allen 23 November 2019 в 02:19
поделиться

Это - классическое пространство по сравнению с компромиссом производительности.

В SQL MS 2005, Varchar (или NVarchar для lanuagues требование двух байтов за символ т.е. китайский язык) являются переменной длиной. Если Вы добавите к строке после того, как она была записана в жесткий диск, то она определит местоположение данных в non-contigious месте к исходной строке и приведет к фрагментации Ваших файлов данных. Это будет влиять на производительность.

Так, если пространство не является проблемой тогда, Символ лучше для производительности, но если Вы хотите подавить размер базы данных тогда varchars, лучше.

2
ответ дан Leo Moore 23 November 2019 в 02:19
поделиться

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

2
ответ дан Guy Starbuck 23 November 2019 в 02:19
поделиться

Многие люди указали, что, если Вы знаете, точная длина значения с помощью CHAR обладает некоторыми преимуществами. Но при хранении штатов США, поскольку CHAR (2) является большим сегодня, когда Вы получаете сообщение от продаж, что 'Мы только что сделали нашу первую продажу Австралии', Вы находитесь в мире боли. Я всегда отправляю к переоценке, сколько времени я думаю, что поля должны будут быть вместо того, чтобы высказать 'точное' предположение для покрытия для будущих событий. VARCHAR даст мне больше гибкости в этой области.

3
ответ дан Craig 23 November 2019 в 02:19
поделиться

CHAR поднимает меньше пространства памяти, чем VARCHAR, если все Ваши значения данных в том поле являются той же длиной. Теперь, возможно, в 2009 база данных на 800 ГБ является тем же, во всех отношениях, как 810 ГБ, если Вы преобразовали VARCHARs в СИМВОЛЫ, но для коротких строк (1 или 2 символа), CHAR является все еще промышленностью "лучшая практика", которую я сказал бы.

Теперь при рассмотрении большого разнообразия типов данных большинство баз данных обеспечивает даже для одних только целых чисел (бит, крошечный, международный, bigint), СУЩЕСТВУЮТ причины выбрать один по другому. Просто выбор bigint каждый раз на самом деле немного незнаком с целями и использованием поля. Если поле просто представляет возраст людей в годах, bigint является излишеством. Теперь это не обязательно "неправильно", но это не эффективно.

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

6
ответ дан Scott Duffy 23 November 2019 в 02:19
поделиться

Я выбрал бы varchar, если столбец не хранит фиксированное значение как Американский Государственный код - который является всегда 2 символами долго, и список допустимого кода штатов США часто не изменяется:).

В любом случае, даже как хранение хешированного пароля (который является фиксированной длиной), я выбрал бы varchar.

, Почему - символьный столбец типа всегда выполняется с пробелами, который делает для столбца my_column определенный как символ (5) со значением 'ABC' внутри comparation:

my_column = 'ABC' -- my_column stores 'ABC  ' value which is different then 'ABC'

ложь.

Этот функция могла привести ко многим раздражающим ошибкам во время разработки и делает тестирование тяжелее.

8
ответ дан Grzegorz Gierlik 23 November 2019 в 02:19
поделиться

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

т.е. - если у Вас есть 2 поля состояния буквы, используйте CHAR (2). Если у Вас есть поле с именами реального положения, используйте VARCHAR.

8
ответ дан Bryan Rehbein 23 November 2019 в 02:19
поделиться

Существуют выигрыши в производительности, но вот тот, который не был упомянут: миграция строки. С символом Вы резервируете все пространство заранее. Поэтому позвольте нам, говорит, что у Вас есть символ (1000), и Вы храните 10 символов, Вы израсходуете все 1 000 символов пространства. В varchar2 (1000), Вы будете только использовать 10 символов. Проблема возникает при изменении данных. Скажем, Вы обновляете столбец, чтобы теперь содержать 900 символов. Возможно, что пространство для расширения varchar не доступно в текущем блоке. В этом случае механизм DB должен переместить строку в другой блок и сделать указатель в исходном блоке к новой строке в новом блоке. Для чтения этих данных механизм DB должен будет теперь считать 2 блока.
Никто не может двусмысленно сказать, что varchar или символ лучше. Существует пространство для компромисса времени и рассмотрение того, будут ли данные обновлены, особенно если существует хороший шанс, что это вырастет.

9
ответ дан Tony BenBrahim 23 November 2019 в 02:19
поделиться

Символ немного быстрее, поэтому если у Вас будет столбец, который Вы ЗНАЕТЕ, то будет определенная длина, использовать символ. Например, храня (M) пиво / (F) emale / (U) nknown для пола или 2 символов для штата США.

18
ответ дан Jarrett Meyer 23 November 2019 в 02:19
поделиться

В дополнение к выигрышам в производительности, CHAR может использоваться, чтобы указать, что все значения должны быть той же длиной, например, столбец для Американских Государственных сокращений.

31
ответ дан Hank Gay 23 November 2019 в 02:19
поделиться

Если бы Вы работаете со мной, и Вы работаете с Oracle, я, вероятно, заставил бы Вас использовать varchar почти при каждом обстоятельстве. Предположение, что char использование меньше вычислительной мощности, чем varchar может быть верным... на данный момент..., но механизмы базы данных поправляются со временем и этот вид общего правила, имеет создание из будущего "мифа".

Другая вещь: Я никогда не видел проблемы производительности, потому что кто-то решил пойти с varchar. Вы будете намного лучше использовать свое время, пишущий хороший код (меньше вызовов к базе данных) и эффективный SQL (как делают индексную работу, как оптимизатор принимает решения, почему exists быстрее, чем in обычно...).

Последняя мысль: Я видел все виды проблем с использованием CHAR, люди, ищущие, '' когда они должны искать '', или люди, ищущие 'НЕЧТО', когда они должны искать 'НЕЧТО (набор пробелов здесь)', или люди, не обрезающие конечные пробелы или ошибки с Powerbuilder, составляющим в целом 2 000 пробелов к значению, это возвращается из процедуры Oracle.

67
ответ дан Hank Gay 23 November 2019 в 02:19
поделиться

Я поддерживаю комментарий Jim McKeeth.

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

, Кроме того, если Вы обновляете столбец VARCHAR к размеру, больше, чем его предыдущее содержание, можно вынудить базу данных восстановить свои индексы (потому что Вы вынудили базу данных физически переместить запись в диск). В то время как со столбцами CHAR этого никогда не будет происходить.

, Но Вы, вероятно, не будете заботиться о хите производительности, если Ваша таблица не будет огромна.

Помнят мудрые слова Djikstra. Ранняя оптимизация производительности является корнем всего зла.

4
ответ дан Alvaro Rodriguez 23 November 2019 в 02:19
поделиться