2013-05-05 3 views
8

Предлог, я знаком с семантическими различиями между значением NULL и пустой строкой.NULL или пустая строка более эффективна/естественна?

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

значение NULL или пустая строка (в этом случае он, вероятно, должен быть VARCHAR, а не CHAR)

я бы стремиться к значению NULL, но я хотел бы иметь это подтвердили или опровергли.

+1

Это своего рода субъективно, но NULL несет в себе значение «неприменимо», которое кажется самым естественным здесь. Эффективность не должна быть фактором. –

+0

@Jack Ну, эффективность всегда является фактором;) – user2352129

+0

Нужно ли быть именам хостов? Вы когда-нибудь ожидали, что несколько IP-адресов разрешат одно и то же имя хоста? –

ответ

4

В MyISAM MYSQL вы сохраняете один бит за строку, не используя NULL. Как указано here:

Объявление столбцов NULL может уменьшить максимальное количество разрешенных столбцов. Для таблиц MyISAM столбцам NULL требуется дополнительное пространство в строке для записи значений NULL. Каждый столбец NULL занимает один бит, округленный до ближайшего байта.

Посмотрите here, а также:

Кроме того, в то время как сам NULL не требует места для хранения, NDB кластер резервы 4 байта на строку, если определение таблицы содержит столбцы, определенные как NULL, до 32 столбцов NULL. (Если таблица кластера MySQL, определяются с более чем 32 NULL столбцов до 64 NULL столбцов, а затем 8 байт в строку зарезервирован.)

Кроме того это также делает работу базы данных быстрее на это указано here (взято из stackoverflow - @DavidWinterbottom ссылки не работаем для меня, я добавил другой Sourse)

Это сложнее для MySQL оптимизации запросов, которые ссылаются на обнуляемый coumns, потому что они делают индексы, статистику индексов и сравнение значений более сложным. Столбец с нулевым значением использует больше пространства для хранения и требует специальной обработки внутри MySQL. Когда индексируемый нулевой столбец индексируется, для него требуется дополнительный байт для каждой записи и может даже привести к тому, что индексом фиксированного размера (например, индексом в одном целочисленном столбце) будет преобразован в переменный размер в MyISAM.

В большинстве случаев не-NULL значения ведут себя более предсказуемо, когда в сочетании с COUNT() и другой агрегационной функции, но вы также можете увидеть, ведут себя NULL в соответствии с вашими потребностями.

Как указано here, не все группы (агрегатные) функции игнорировать NULL, например, COUNT() даст вам другой результат, который COUNT(*) для столбца, содержащего NULL значения.

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

+0

Явное поведение никогда не было проблемой для меня. Не могли бы вы опубликовать ссылку на ваш респектабельный аргумент о размере бит NULL? С другой стороны, «это также ускоряет работу базы данных», можно использовать некоторые дополнительные демонстрации. (больше не всегда означает медленнее) – Sebas

+0

@Legat Смогу ли я сохранить этот бит?Я предполагаю, что это будет часть некоторой внутренней коллекции флагов, поэтому она всегда будет там и займет пространство, просто не оценивается, если NULL не разрешен. – user2352129

+0

Благодарим вас за упоминание вашего источника. Я вижу, что это ясно говорит о MYISAM, что означает, что механизм innodb освобожден. – Sebas

1

Oracle решил проблему и интерпретировал ее как то же самое.

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

Плюс, с точки зрения значимости ключевых слов, NULL - это именно то, что вы хотите, потому что это означает «неизвестно» в семантике db. (исправьте меня, если я ошибаюсь)

+1

Что касается семантики, я согласен, вот почему я также скорее склоняюсь к NULL, но мне интересно, может ли пустая строка иметь потенциальное преимущество в производительности или размере памяти (для IIRC NULL требуется дополнительный флаг). ...... Что касается Oracle, я не знал об этом и узнал только в процессе моих исследований, но я действительно не согласен с ними. Пустая строка не всегда имеет то же значение, что и NULL, и, следовательно, не должна быть автоматически преобразована – user2352129

+0

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

+0

С точки зрения производительности или хранения, вы лично не предпочли бы либо над другим, хотя? – user2352129

0

Я рекомендую вам использовать NULL, в то время как тип NULL отличается от строки. Например, проще отфильтровать строки с этим значением или определить тип значения в этом поле и так далее.

+1

Но вы также можете легко фильтровать пустую строку. – user2352129

1

Первый: Рассмотрим внимательно различные семантику NULL и пустая строка.

  • Первый лучше всего интерпретировать как что-то вроде:
    Существует допустимое значение для этого поля, но это значение еще не известно.
  • Второй всегда означает:
    Допустимое значение для этого поля известно, и это точно "".

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

Третьего: Признать, что все выражения, которые используют NULL восприимчивы к не-интуитивности трехзначной логики, если NULL не религиозно соединялись в пустой строки (или какое-либо другое контекстуально допустимое значение) первым , В частности, закон исключенного среднего больше не применяется, поэтому выражение A или ~ A больше не является тавтологически истинным всякий раз, когда оценка A требует оценки NULL. Забыть это может привести к очень тонким и труднодоступным ошибкам.

не-равно оператор выставляет это регулярно:

When A has the value NULL: 
    The expression A = 0 returns false; 
    The expression A <> 0 returns false; and 
    The expression A OR NOT A returns false! 

Update:
Я думаю, суть моей точки является то, что они не одни и те же существа, а очень разные звери. Каждое имеет свое место. Второе поле адреса всегда должно быть не нулевым (если вы не намереваетесь разрешить ввод неполных или неполных адресов), и оно по умолчанию всегда должно быть допустимым и известным значением Empty-String. NULL должен быть ограничен случаями, когда действительное и известное значение будет предоставлено позже, и на самом деле o сигнализировать о некотором отказе валидации, который должен быть разрешен.

Из OP ниже:

Строка не будет обновляться. При вставке есть либо адрес IP , либо нет (потому что он не может быть разрешен).

Ответ:

Тогда я рекомендую использовать пустая строка по умолчанию, и сделать поле NON-NULL. Используйте только NULL, когда вы должны, так как у него есть тонкие недостатки.

+0

Я добрался до последнего абзаца. В моем случае можно было бы утверждать оба решения (NULL, хост не может быть разрешен и неизвестен - «", хост не может быть разрешен, но была сделана попытка, поэтому результат пуст). ........ Из вашего ответа я не совсем понял, какое решение вы бы выбрали, не могли бы вы рассказать об этом? – user2352129

+0

@ user2352129: Я предполагаю, что суть моей точки в том, что они ** НЕ ** одно и то же существо, а совсем разные звери. Каждое имеет свое место. Второе поле адреса всегда должно быть не нулевым (если вы не укажете _intend_, чтобы разрешить ввод неполных или неполных адресов), и это значение по умолчанию всегда должно быть значением _valid и known_ ** Empty-String **. ** NULL ** следует ограничивать случаями, когда значение _valid и known_ будет предоставлено позже, и на самом деле o сигнализировать о некотором отказе валидации, который должен быть разрешен. ... –

+0

@ user2352129: В вашем примере я не вижу, где вы определили семантику этого поля, чтобы сделать определение. Я подозреваю, что вы должны сделать поле нулевым, но определить его значение по умолчанию как ** Empty-Sting **. Таким образом, приложение может назначить ** NULL ** явно означать «Оно существует, но мне нужно найти значение»; но по умолчанию создается исходная запись ** Empty-String **, означающая «Не имеет». Это правильная семантика вашей строки таблицы? –

Смежные вопросы