2013-09-02 3 views
4

и заблаговременно за вашу помощь.Mysql: Храните массив данных в одном столбце

Хорошо, это мое положение. У меня есть веб-система, которая производит некоторые шумовые вычисления на основе образца, созданного сономером. Первоначально база данных сохраняла результаты этих вычислений. Но теперь меня попросили также хранить сами выборки. Каждый образец представляет собой список из 300 или 600 номеров с 1 десятичной единицей.

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

Мой вопрос: тогда как лучше всего хранить этот список чисел в одном столбце?

Вещи рассмотреть:

  • было бы хорошо, если бы этот список может быть прочитана как PHP и JavaScript без каких-либо дальнейших осложнений.
  • Этот список полезен только в том случае, если он получен в его совокупности, поэтому я бы не стал нормализовать его. также вычисления, сделанные в этом списке, являются сложными и уже закодированы в PHP и javascript, поэтому я не буду выполнять SQL-запросы на элементах данного списка

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

Спасибо большое и иметь хороший день/вечер :)

+0

Таким образом, вы просто хотите сохранить большой список номеров в базе данных? Правильно ли я понимаю вас? –

+1

Вы можете сохранить его как JSON. – elclanrs

+0

300 номеров, по одной десятичной, каждая по одной цифре каждая? Если так, то строка будет простейшей. –

ответ

6

Прежде всего, вы действительно не хотите этого делать. Столбец в СУБД должен быть атомарным, поскольку он содержит один и только один фрагмент информации. Попытка хранить более одной части данных в столбце является нарушением первой нормальной формы.

Если вам это абсолютно необходимо, вам необходимо преобразовать данные в форму, которая может быть сохранена как отдельный элемент данных, как правило, строка. Вы можете использовать механизм serialize() PHP, синтаксический анализ XML (если данные являются деревом документа), json_encode() и т. Д.

Но как вы эффективно обрабатываете такие данные? Ответ в том, что вы не можете.

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

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

ОБНОВЛЕНИЕ: меня спрашивали о требованиях к хранению данных, как в том, будет ли одна строка дешевле с точки зрения хранения. Ответ таков: в типичных случаях это не так, и в тех случаях, когда ответ да, цена, которую вы платите за него, не стоит платить.

Если вы используете таблицу с двумя столбцами (1 столбец для внешнего ключа записи, к которой принадлежит образец, по одному для одного образца), то для каждого столбца в худшем случае потребуется 16 байт (8 байтов для ключа longint столбец, 8 байтов для числа с плавающей запятой двойной точности). Для 100 записей - 1600 байт (игнорирование служебных данных db).

Для последовательной строки вы храните в лучшем случае 1 байт на символ в строке. Вы не можете знать, как долго будет эта строка, но если мы предположим, что 100 образцов со всеми сохраненными данными каким-то надуманным совпадением все падают между 10000.00 и 99999.99, причем там только 2 цифры после десятичной точки, пересматривая 8 байтов на образец. В этом случае все, что вы сохранили, это накладные расходы внешних ключей, поэтому требуемый объем памяти составляет 800 байт.

Это, конечно, основано на множестве предположений, таких как кодировка символов всегда является 1 байт на символ, строки, которые составляют образцы никогда не быть длиннее 8 символов и т.д.

Но, конечно есть также накладные расходы любого механизма, который вы используете для сериализации данных. Абсолютный простейший метод, CSV, означает добавление запятой между каждым образцом. Это добавляет n-1 байт к сохраненной строке. Таким образом, приведенный выше пример теперь будет 899 байт, и это с простейшей схемой кодирования. JSON, XML, даже сериализации PHP все добавляют больше служебных символов, чем это, и вы скоро будете иметь строки, которые намного длиннее 1600 байт. И все это связано с предположением о кодировании 1 байтового символа.

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

И, конечно, если ваши образцы начинают добавлять больше цифр, хранилище данных увеличивается. 39281.3392810 не будет сохраняться в 8 байтах как строка, даже в лучшем случае.

И если данные сериализованы, база данных не может манипулировать. Вы не можете сортировать образцы, выполнять какие-либо математические операции над ними, база данных даже не знает, что они цифры!

Чтобы быть честным, хранение в наши дни смехотворно дешево, вы можете купить несколько ТВ-накопителей для крошечных сумм. Действительно ли хранилище действительно критично? Если у вас сотни миллионов записей, я сомневаюсь, что это так.

Вы можете проверить книгу под названием SQL Antipatterns

+0

Вопрос для вас: нет ли накладных расходов, связанных с хранением для каждого номера с каждым идентификатором записи и каждым идентификатором выборки? или движок db хранит его как массив? если нет, то, возможно, сохранение его в сериализованном виде в одной ячейке или если все образцы имеют одинаковый размер в одной строке, может быть лучше, нет? что данные могут храниться только для ведения записей и обычно не извлекаются, если не требуется аудит. – Daren

+1

@ GordonM - превосходное объяснение. Я как-то думал, что такая структура данных будет хорошим выбором для таблицы динамических значений с несколькими типами данных (текстовый, десятичный, множественный и один выбор, выбор плюс текст). О, ужас ... –

+0

@daren См. Текущее обновление для ответа. Что касается «Я только храню его для ведения записей», вы не знаете, что это требование останется в камне. Что делать, если вам нужны данные позже? – GordonM

2

Я бы рекомендовал создать отдельную таблицу с тремя столбцами для образцов. Один из них будет идентификатором записи, второй - идентификатором образца, а третий - значением. Конечно, если в вашей основной таблице нет уникального столбца id, вам нужно будет создать его и использовать в качестве внешнего ключа.

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

UPDATE Как GordonM и Дарины подробно ниже, аргумент памяти не обязательно действует (см ниже для дальнейшего объяснения), но есть и другие причины против упорядоченного подхода.

И, наконец, это не связано с сложным php-java-скриптом и довольно прямолинейно коду.

+0

вопрос для вас: нет ли накладных расходов, связанных с хранением для каждого номера с каждым идентификатором записи и каждым идентификатором выборки? или движок db хранит его как массив? если нет, то, возможно, сохранение его в сериализованном виде в одной ячейке или если все образцы имеют одинаковый размер в одной строке, может быть лучше, нет? – Daren

+0

Вы имеете в виду память? Я не большой специалист в области сериализации, но, насколько я понимаю, это означает хранение данных в виде символов. Если да, то в ** Вариант A ** 300 строк x 3 столбцов FLOAT = 3600 байт. ** Вариант B ** 300 номеров, скажем, в пределах 8 цифр (10 символов, включая точку и знак «+»/«-») + некоторые символы для идентификаторов -> допустим, составляют символ (3000), который составляет 9000 байт в UTF8. Моя математика и логика, вероятно, превышают вершину, поэтому я, скорее всего, ошибаюсь, но, поначалу, кажется, что масштабы в пользу варианта А. Не говорить о дополнительных усилиях по сериализации. –

+1

Если вы храните цифры, то utf-8 является отходами, ASCII более чем достаточно, так что сбрасывает ваше приближение на треть, что делает его конкурентоспособным с вариантом A, но GordonM ниже любезно расширился, так что вы получили меня убежденный на 95% уже, не нужно настаивать. :) – Daren

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