Когда использовать VARCHAR и DATE/DATETIME
поэтому у нас было это обсуждение программирования на Freenode, и этот вопрос возник, когда я пытался использовать VARCHAR (255) для хранения Date Variable в этом формате: D/MM/YYYY. Поэтому вопрос в том, почему так плохо использовать VARCHAR для хранения даты. Ее преимущества:
- Быстрее его кодировать. Раньше я использовал DATE, но форматирование даты было настоящей болью.
- Ей больше нравится голова использовать строку, чем Date? Кто заботится, мы живем в эпоху ГГц.
- Это неэтично правильно (lolwut?) Это то, что мне сказал другой пользователь...
Итак, что бы вы предпочли использовать для хранения даты? SQL VARCHAR или SQL DATE?
Ответы
Ответ 1
Когда у вас будет база данных с более чем 2-3 миллионами строк, вы поймете, почему лучше использовать DATETIME, чем VARCHAR:)
Простой ответ заключается в том, что с базами данных - вычислительная мощность больше не проблема. Просто размер базы данных зависит от времени поиска HDD.
В основном с современными жесткими дисками вы можете читать около 100 записей в секунду, если они читаются в случайном порядке (обычно это случай), поэтому вы должны делать все возможное, чтобы минимизировать размер БД, потому что:
- Головкам жестких дисков не придется "путешествовать" так много.
- В RAM вы поместите больше данных.
В конце концов, это всегда время поиска HDD, которое убьет вас. Например. некоторый простой запрос GROUP BY со многими строками может занимать пару часов, когда делается на диске, по сравнению с несколькими секундами, когда выполняется в RAM = > из-за времени поиска.
Для VARCHAR вы не можете выполнять поиск. Если вы ненавидите то, как SQL имеет дело с датами, просто используйте временную метку unix в 32-битном целочисленном поле. У вас будут (в принципе) все преимущества использования поля SQL DATE, вам просто нужно будет манипулировать и форматировать даты с помощью выбранного языка программирования, а не SQL-функций.
Ответ 2
Почему бы не надеть винты с молотком?
Потому что это не правильный инструмент для работы.
Некоторые из недостатков версии VARCHAR:
- Вы не можете легко добавить/вычесть дни в версию VARCHAR.
- Тяжелее извлекать только месяц/год.
- В столбце VARCHAR базы данных нет ничего, что помещало бы вам ненужные данные.
- Версия VARCHAR специфична для культуры.
- Вы не можете легко отсортировать даты.
- Трудно изменить формат, если вы хотите позже.
- Это нетрадиционные, что усложнит понимание другими разработчиками.
- Во многих средах использование VARCHAR будет использовать больше места для хранения. Это может не иметь значения для небольших объемов данных, но в коммерческих средах с миллионами рядов данных это может иметь большое значение.
Конечно, в ваших проектах хобби вы можете делать то, что хотите. В профессиональной среде я бы настаивал на использовании правильного инструмента для работы.
Ответ 3
Две причины:
- Сортировка результатов по датам
- Нечувствителен к изменениям форматирования даты.
Итак, возьмем, например, набор записей, которые выглядят следующим образом:
5/12/1999 | Frank N Stein
1/22/2005 | Drake U. La
10/4/1962 | Goul Friend
Если мы должны были хранить данные по вашему пути, но отсортированы по датам в выражении порядка SQL, ответьте с помощью набора результатов, который выглядит следующим образом:
1/22/2005 | Drake U. La
10/4/1962 | Goul Friend
5/12/1999 | Frank N. Stein
Если бы мы сохранили даты как DATETIME, SQL будет правильно реагировать на их порядок следующим образом:
10/4/1962 | Goul Friend
5/12/1999 | Frank N. Stein
1/22/2005 | Drake U. La
Кроме того, если где-то по дороге вам нужно было отображать даты в другом формате, например, как YYYY-MM-DD, тогда вам нужно будет преобразовать все ваши данные или обработать смешанный контент. Когда он хранится как SQL DATE, вы вынуждены делать преобразование в коде и, вероятно, имеете одно место для изменения формата для отображения всех дат - бесплатно.
Ответ 4
Я проголосовал бы за использование типов date/datetime, просто для простоты/согласованности.
Если вы сохраните его как строку символов, сохраните его в формате ISO 8601:
Кроме того, строка даты/времени ISO 8601 (A) правильно сортируется, (B) являются читабельными для человека, (C) являются языковыми, а (D) легко конвертируются в другие форматы. Для шпаргалки из серии ISO, строки ISO 8601 предлагают
для следующего:
- Дата
- Время суток
- Скоординированное универсальное время (UTC)
- Локальное время со смещением к UTC
- Дата и время
- Временные интервалы
- Периодические интервалы времени
Представления могут быть в одном из двух форматов: базовый формат который имеет минимальное количество символов и расширенный формат который добавляет символы для повышения удобочитаемости человека. Например, третий январь 2003 года может быть представлен как 20030103 или 2003-01-03.
[и]
предлагают следующие преимущества перед многими из локально используемых представления:
- Легко читаемые и записываемые системами
- Легко сопоставимый и сортируемый
- Не зависит от языка
- Большие единицы записываются перед меньшими единицами
- Для большинства представлений обозначения короткие и постоянной длины
Последнее: если все, что вам нужно сделать, это сохранить дату, то сохранение ее в короткой форме ISO 8601 YYYYMMDD в столбце char (8) не требует больше памяти, чем значение datetime (и вы не знаете, t нужно беспокоиться о 3 миллисекундном промежутке между последним тиком одного дня и первым тиком следующего. Но это вопрос для другого обсуждения. Если вы разделите его на 3 столбца, YYYY char(4), MM char(2), DD char(2)
, вы будете использовать до тех пор, пока у вас не будет одинакового объема памяти, и получите больше опций для индексирования. Еще лучше сохраните поля как короткие для yyyy (4 байта) и tinyint для каждого из MM и DD — теперь вы уменьшаете до 6 байт для Конечно, недостаток, заключающийся в разложении компонентов даты на их составные части, заключается в том, что преобразование в соответствующие типы данных даты/времени затруднено.
Ответ 5
Между DATE/DATETIME
и VARCHAR
для дат я буду ходить с DATE/DATETIME
каждый раз. Но есть пропущенный третий вариант. Хранение его как INTEGER без знака!
Я решил пойти с INTEGER unsigned
в моем последнем проекте, и я действительно доволен тем, что сделал этот выбор, вместо того, чтобы хранить его как DATE/DATETIME
. Поскольку я проходил по датам между клиентом и сервером, он стал идеальным типом для меня. Вместо того, чтобы хранить его как DATE
и при необходимости конвертировать обратно каждый раз, когда я выбираю, я просто выбираю его и использую его, но я хочу его. Если вы хотите выбрать дату как "удобную для человека" дату, вы можете использовать функцию FROM_UNIXTIME()
.
Также целое число занимает 4 байта, а DATETIME
занимает 8 байтов. Экономия 50% памяти.
Проблема сортировки, которую предлагает Берин, также решается с использованием целого числа в качестве хранилища для дат.