Как хранить массив в mysql
Перейти к содержимому

Как хранить массив в mysql

  • автор:

Как в MySQL засунуть массивы?

php: serialize / unserialize
все так в основном делают.

#2
13:22, 31 июля 2005

Dexus
спасибо 🙂

#3
13:51, 31 июля 2005

wat
Пожалуйста 🙂
но на самом деле и split/join с запятыми (или какими-нибудь ддругими спец-символами) тоже — неплохой метод.
Serialize/unserialize — для чего-то более структурно-сложного, чем просто одномерный массив.

#4
14:20, 31 июля 2005

wat что-то замышляет.
определенно.
А запихнуть — смотря какой массив.
Вопервых надо подумать — а стоит ли. Одно дело, если массив фиксированого размера, тогда порядок, но если нет, то встает вот какая проблема: если в sql таблице есть поля с произвольным размером (text или blob, а последний — какраз для хранения таких вот сериализованых массивов), то скорость доступа к этой таблице значительно уменьшается.
Потом. Большие массивы опасны тем, что для доступа в скрипте к одному элементу придется выковыривать весь массив целиком (в память), а оттуда выковыривать нужный элемент. Надо очень долго шаманить, чтобы минимизировать ресурсоекость скрипта, работающего с этим массивом (еще больше шаманить надо, когда надо наладить работу несколькихз паралельных скриптов, тут уж без бубна совсем никак).
И последнее если массив маленький, и должен быть в каждой записи — а не заменить ли его полями, если массив большой и должен быть в каждой записи — не жалко ли места (не отказаться ли от него), если массив большой, и нужен далеко не в каждой записи — не завести ли доп. таблицу.

#5
14:56, 31 июля 2005

Что бы потом не гемороится, лучше сделать так: В ячейке сохранять имя отдельной таблицы, в которую уже можно поместить массив. Так по крайней мере, на тебя не будут давлеть ни какие ограничения. Имя таблицы может генерироваться автоматически (это просто связка префикс-ID, где префикс нужен для того что бы такие таблицы можно было легко визуально отделить от остальной БД).
Кста, при большом количестве и размере массивов ты так выиграешь в скорости.

  • Sbtrn. Devil
  • Постоялец

#6
15:08, 31 июля 2005

Или завести большую универсальную таблицу с полями (оба индексные): имя массива, индекс массива. + остальные поля, как данные ячеек массива. А ссылать на массив посредством указания его имени. Тут, по-хорошему, надо б ещё привлечь отношения таблиц 1много, но не всегда это может оказаться позволительно.

#7
15:21, 31 июля 2005

DimaSun
Согласен, лучше чуть-чуть сменить дизайн базы и воспользоватся преимуществами sql запросов. Но лучше для массивов сделать одну таблицу и дифферинциировать массивы по некому полю. (хотя конечно зависит от)

#8
16:12, 31 июля 2005

Массивы могут иметь разную размерность, тут не очень удобно получится.

#9
20:21, 31 июля 2005

DimaSun
Вот что я имал в виду. Например пользователю нужно сопоставить массив целых чисел, делаем что-то типа этого:

CREATE TABLE user_ints
( user_id INT NOT NULL,
value INT NOT NULL,
INDEX(user_id)
);
Если нужно, можно ввести колонку определяющую порядок значений (локально для пользователя или глобально для таблицы), время создания и т.п.
Если индексировать и value, то можно быстро удалять сами значения не перебирая всех пользователей.

#10
21:48, 31 июля 2005

Это хорошо. А если массив двумерный? А если их несколько (Вообще в БД), и они действительно разной размерности?
Я думаю мы оба правы, но рассматриваем несколько разные случаи. 🙂 Мы не знаем конкретной задачи.

#11
22:32, 31 июля 2005

у базы данных не бывает полей произвольного размера. TEXT например занимает фиксированно 32 килобайта

#12
23:04, 31 июля 2005

keltar
Фигю какую то ты сказал
В MySQL есть три вида текстового поля:
text — 2^16 байт (64К)
mediumtext — 2^24 байт (16Мб)
lolgtext — 2^32 байт (4Гб)

с блобами та же история.
Только это _максимальный_ размер поля.
База не будет резервировать по 16 мегабайт для каждого mediumtext поля, как и 65 кб для обычного текстового. БД динамично места выделяет.

#13
9:29, 1 авг 2005

Если MySQL использовать из C++ с Unix компилятором gcc, то можно в поле TEXT, MEDIUMTEXT или LONGTEXT запихивать массив, как дам его памяти без serialize / unserialize, предварительно сделав addslashes.
А в PHP числа в переменных в наглую приводятся к текстовой записи, что часто не удобно.
Если массив короткий, то можно сделать в php числа через ‘;’ или ‘,’ в виде строки текста, как Wat написал. Но если нужно хранить огроменные массивы, то php’шный serialize на столько увеличивает память для его хранения, что #$#@@.

Чтобы предварительно писать скрипты на C++ под виндой в Microsoft Visual Studio и с MySQL, нужно скачать полную версию MySQL под винды с частью интерфейсных файлов C++, файлом mysql.h . Его можно подключать и юзать MySQL в сях. Если не использовать подключение нестандартных библиотек, то обычно отлично компилится написанная прога и под Unix. Только нужно запускаемый скомпилленый бинарный файл в Unix переименовать в *.cgi и поставить права, как у cgi перловских скриптов и под многими хостингами с разрешённым исполнением бинарников отлично работает.

Другой способ, но много памяти хавает — как уже описали. Создать отдельную таблицу с полями

CREATE TABLE table_array
(
parentId INT, — ссылка на id родителя, которому принадлежит массив
value INT, — значение одного из элементов массива

PRIMARY KEY (parentId, value)
)

Массив можно получать

SELECT value FROM table_array WHERE parentId = $myParentId

#14
9:50, 1 авг 2005

Volodya
Мне думается что хранить массив в бинарном виде в PHP тоже можно. делать подобную «упаковку», если это те же числа.
по типу charint=chr((number>>24)&255).chr((number>>16)&255).chr((number>>8)&255).chr(number&255).
в обратную сторону преобразовывать через ord()

Как хранить массивы в базе данных

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

Чтобы конвертировать любой массив (или объект) в строку в PHP, нужно вызвать функцию serialize:

$array = array( 1, 2, 3 );
$string = serialize( $array );
echo $string;

$string содержит строчную версию массива. Выше приведенный пример выведет следующее:

Чтобы конвертировать такую строку обратно в массив, надо использовать unserialize:

// $array будет содержать( 1, 2, 3 )

$array = unserialize( $string );

Теперь проведём конвертацию массива из 200 случайно генерированных целых чисел в диапазоне от 1 до 1000:

$array = array(); 2 for( $i = 0; $i < 200; $i++ )
$array[] = mt_rand( 1, 1000 );
$string = serialize( $array );
echo $string;

Пример выведет подобную строку:

Данная строка может быть сохранена в базе данных и конвертирована в массив по мере надобности. Очень часто функция base64_encode используется в сочетании с функцией serialize для хранения массивов:

$string = base64_encode( serialize( $array ) );

Зашифрованная строка может быть восстановлена в массив с помощью функции base64_decode:

$array = unserialize( base64_decode( $string ) );

К сожалению, такие строки могут иметь очень большой размер. В таком случае можно использовать функцию gzcompress для сжатия строки (размер сжатой строки существенно меньше):

$smallString = gzcompress( $string );

Перед использованием, такую строку надо вернуть к обычному виду с помощью функции gzuncompress.

Как правильно хранить данные в формате «МАССИВ» в SQL?

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

Т.е. если основная сущность лежит в таблицe SomeTable c PK SomeTableID, то массив можно положить в SomeTableArray вида:

ArrayValueID | SomeTableID (FK) | Value 1 | 1 | string1 2 | 1 | string2 3 | 2 | string3 4 | 2 | string4 

Это добавит лишний запрос на чтение, но зато у вас будет нормально работать поиск. И намного проще будет проводить добавление новых элемента в массив.

Все другие варианты — хранение в виде строки (json/xml/csv) — вынудят вас при каждом поиске, например, string2, выбирать вообще все значения из базы в память и как-то их там парсить. Полноценно работать с ними на уровне БД не получится.

Отслеживать
ответ дан 13 дек 2015 в 19:09
user177221 user177221

@semiromid это зависит от наличия индексов. Поиск по индексу работает быстро — практически мгновенно.

– user177221
13 дек 2015 в 20:27

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

14 дек 2015 в 5:15

@semiromid ну так создайте индекс, в чем проблема. не совсем понял что значит «уникальные индексы для каждой записи в первой таблице» — индексы работают не так. Создаете неуникальный индекс по UserID в таблице друзей — и он работает для поиска сразу по всем пользователям.

– user177221
14 дек 2015 в 6:52

@AlexceiShmakov Причем тут размер массива? Проблема не размере, а в том, что для поиска вам надо будет вычитать все массивы (все строки). Как, например, должен работать поиск «все строки, у которых в массиве есть 3» в вашема случае? Вычитать из базы все строки. Распарсить все массивы. Поискать в каждом массиве. Как вы себе это представляете для миллионов записей? А индекс в БД — это прошитое B-Tree. в нем такой поиск займет O(log n)

– user177221
14 дек 2015 в 6:58

@semiromid разберитесь что такое индексы и как они работают. они не создаются для строк или для конкретных значений. Они создаются сразу для всей колонки. И позволяют быстро (очень быстро) искать по значению или по диапазону. Т.е. индекс по (UserID) позволяет быстро выбрать все записи для одного пользователя. Индекс по (UserID, FriendID) позволяет быстро определить, является ли конкретный пользователь другом другого. И индексы и ключи надо подбирать под конкретную структуру данных и под конкретные запросы.

Как хранить массивы в базе данных?

Есть PHP скрипт. Генерируется массив. Каким образом можно хранить его в базе данных(MySQL) дабы при обращении было легко им манипулировать? И что, если массив состоит из других массивов? Хотелось бы увидеть небольшие примеры кода, или в крайнем случае, ссылки, что можно использовать. Спасибо.

Array ( [grounds] => Array ( [1] => Array ( [date] => 2014-05-28 [timeStart] => 8:45 [timeEnd] => 9:45 [groundId] => 1 [price] => 1500 ) [2] => Array ( [date] => 2014-06-4 [timeStart] => 8:45 [timeEnd] => 9:45 [groundId] => 2 [price] => 1800 ) ) [count] => 2 [summ] => 3300 )
  • Вопрос задан более трёх лет назад
  • 35529 просмотров

Комментировать

Решения вопроса 2

GingerbreadMSK

Алексей Кулешов @GingerbreadMSK

1. serialize/unserialize (для хранения в БД самое то)
2. JSON (если нужен обмен через AJAX без преобразований)

Ответ написан более трёх лет назад

Нравится 7 2 комментария

another_dream

Дмитрий @another_dream Автор вопроса

serialize подойдет для ассоциативного массива, в который вложено еще пару таких же?

GingerbreadMSK

Алексей Кулешов @GingerbreadMSK

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *