char vs varchar для производительности в базе данных - PullRequest
12 голосов
/ 08 декабря 2008

Я использую mySQL для настройки базы данных опционов на акции. Есть около 330 000 строк (каждая строка 1 вариант). Я новичок в SQL, поэтому я пытаюсь определить типы полей для таких вещей, как символ опции (от 4 до 5 символов), символ акций (от 1 до 5 символов), название компании (от 5 до 60) символы).

Я хочу оптимизировать скорость. Оба создают базу данных (что происходит каждые 5 минут по мере появления новых ценовых данных - у меня нет потока данных в реальном времени, но он близок к реальному, так как я получаю новый текстовый файл с 330 000 строк, доставленных мне каждые 5 минут; эти новые данные полностью заменяют предыдущие данные), а также для скорости поиска (будет веб-интерфейс, где многие пользователи могут запускать специальные запросы).

Если меня не беспокоит пространство (поскольку время жизни БД составляет 5 минут, а каждая строка содержит, может быть, 300 байтов, так что, возможно, 100 МБ для всего этого), то какой самый быстрый способ структурировать поля?

Фактически, тот же вопрос для числовых полей: есть ли разница в производительности между int (11) и int (7)? Работает ли одна длина лучше, чем другая, для запросов и сортировки?

Спасибо!

Ответы [ 5 ]

33 голосов
/ 08 декабря 2008

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

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

Что касается INT (7) и INT (11), это не имеет отношения к хранению или производительности. Это распространенное заблуждение, что аргумент MySQL для типа INT имеет какое-либо отношение к размеру данных - это не так. Тип данных INT MySQL всегда 32-битный. Аргумент в скобках относится к количеству цифр для заполнения, если вы отображаете значение с помощью ZEROFILL. Например. INT (7) отобразит 0001234, где INT (11) отобразит 00000001234. Но это заполнение происходит только при отображении значения, а не во время хранения или математического вычисления.

6 голосов
/ 08 декабря 2008

Если фактические данные в поле могут сильно различаться по размеру, лучше использовать varchar, поскольку он приводит к уменьшению количества записей, а меньшие записи означают более быструю БД (большее количество записей может поместиться в кэш, меньшие индексы и т. Д.). По той же причине лучше использовать меньшие целые, если вам нужна максимальная скорость.

OTOH, если дисперсия мала, например, поле имеет максимум 20 символов, и большинство записей на самом деле имеют длину почти 20 символов, тогда лучше использовать char, поскольку он допускает некоторую дополнительную оптимизацию БД. Однако это действительно имеет значение, только если это верно для ВСЕХ полей в таблице, потому что тогда у вас есть записи фиксированного размера. Если ваша главная задача - скорость, возможно, стоит даже переместить любые поля нефиксированного размера в отдельную таблицу, если у вас есть запросы, которые используют только поля фиксированного размера (или если у вас есть только запросы дробовика).

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

4 голосов
/ 08 декабря 2008

Учитывая ваши системные ограничения, я бы предложил varchar, так как все, что вы делаете с данными, должно будет соответствовать любому заполнению, которое вы добавите, чтобы использовать символ фиксированной ширины. Это означает, что больше кода где-то, что больше для отладки, и больше возможностей для ошибок. Как говорится:

Основным узким местом в вашем приложении является сброс и повторное создание базы данных каждые пять минут. Вы не получите большого выигрыша в производительности благодаря микро улучшениям, таким как выбор char вместо varchar. Я считаю, что вместо этого у вас есть более серьезные архитектурные проблемы. - Принцесса

Я согласен с приведенным выше комментарием. У вас есть более крупная рыба, чтобы жарить ее, прежде чем вы сможете позволить себе беспокоиться о разнице между чарсом и варчаром. С одной стороны, если у вас есть веб-пользователь, пытающийся выполнить специальный запрос, и база данных находится в процессе пересоздания, вы получите ошибки (т. Е. Проблемы типа «база данных не существует» или просто «истекло время ожидания») ).

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

1 голос
/ 04 января 2010

Также помните, что создание баз данных зависит от фактической реализации базы данных, которую вы используете. Если вы когда-нибудь перенесетесь с MySQL, скажем, на Postgresql, вы обнаружите очень неприятный факт, что создание баз данных в postgresql - это сравнительно очень медленная операция. Например, это на несколько порядков медленнее, чем чтение и запись строк таблицы.

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

1 голос
/ 07 апреля 2009

Я бы точно не создавал базу данных каждый раз. Вместо этого я бы сделал следующее:

  • прочитайте в файле обновления / снимка и создайте некоторый объект, основанный на каждой строке.
  • для каждой строки получить символ / имя опции (уникальное) и установить его в базе данных

Если бы это был я, я бы также имел в кеше в памяти все символы и данные о текущей цене.

Данные о ценах никогда не являются целыми числами - вы можете использовать символы.

Название компании, вероятно, не уникально, так как существует множество вариантов для конкретной компании. Это должен быть индекс, и вы можете сэкономить место, просто используя идентификатор компании.

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

Наличие доступа к запросу для других пользователей также является причиной НЕ продолжать удалять и создавать базу данных.

...