Бинарный файл PHP

1 23
C
На сайте с 22.08.2012
Offline
104
#21
Shelton724 #:

Ну (раз уж id известные и просто числовые) тогда сделайте не один файл, а (например) 1000. По принципу в первом с id от 0 до 1000, во втором от 1001 до 2000 и т.п. Ну и обращаться к нужному в зависимости от диапазона.

И вот мы начали создавать собственный unordered_map/hashtable :)

C
На сайте с 22.08.2012
Offline
104
#22
LEOnidUKG #:

чем вас sqlite с индексом не устроил не понятно, уже бы запустили и всё работало. Если надо просто поместите бд файл в память и всё будет работать еще быстрее.

B-Tree и при этом хранить в памяти?

Тогда уж redis.

LEOnidUKG
На сайте с 25.11.2006
Offline
1727
#23
chaturanga #:

B-Tree и при этом хранить в памяти?

Тогда уж redis.

Если площадка позволяет, я не против. Применять технологии именно так как требуется.

✅ Мой Телеграм канал по SEO, оптимизации сайтов и серверов: https://t.me/leonidukgLIVE ✅ Качественное и рабочее размещение SEO статей СНГ и Бурж: https://getmanylinks.ru/
WS
На сайте с 01.11.2008
Offline
136
#24

подсказываю:

- во-первых хранить идентификаторы неразумно, тк придётся лазить по всему объёму данных

- чтобы не лазить по всему объёму данных надо сделать фиксированный размер записей, аналог char в mysql

- номером (идентификатором) записи будет просто номер записи в вашем бинарнике, если такого идентификатора не существует, просто заполняйте фиксированный объём нулл байтами

Итого:

имеем массив вида

$data= [
  5 => 'ivan',
  14 => 'vova',
  12=>'Sergio'
]
1 - сортируем по возрастанию по ключам 5,12,14 (ksort)

2 - определяем минимальное и максимальное значение ключей массива, в нашем случае $min = 5, $max=14, а также максимальную длину имени в байтах (по strlen), в нашем случае максимальная длина имени у Sergio, равна $maxnamelen = 6

3 - формируем датафайл:

$f = fopen(__DIR__ . '/person.bin','wb+');
for($i=0;$i<=$max;$i++)
{
        if(isset($data[$i]))
        {
                fwrite($f, pack('a'. $maxnamelen , $data[$i] ));
        }
        else
        {
                fwrite($f, pack('a'. $maxnamelen , '' ));
        }
}
fwrite($f, pack('C',$maxnamelen ));//последний байт датафайла будет нам говорить о максимальной длине имени
fclose($f);

4 - при поиске, по датафайлу, определяем размер датафайла в байтах (filesize), читаем последний байт, определяем максимальную длину имени в байтах, определяем, количество блоков, деля размер датафайла на максимальную длину имени в байтах и читаем файл с нужного места, умножая $id на максимальную длину имени в байтах (идентификатор - это номер записи в датафайле)

ps: собственно поиска то и никакого не будет, вы будете просто дважды читать датафайл - первый раз, чтобы выгрести максимальную длину имени в байтах, а второй, чтобы прочитать само имя с нужного места датафайла (fseek, fread), быстрее некуда

lutskboy
На сайте с 22.11.2013
Offline
173
#25

хорошая идея. взял на заметку.

fwrite($f, pack('a'. $maxnamelen , $data[$i] )); а вот эта штуковина не раздует слишком файл?

если например имя одно 3 символа. а другое 32. то он забьет чем эти пространства? дополнит 3 до 32 чем? 

надо попробовать

WS
На сайте с 01.11.2008
Offline
136
#26
lutskboy #:

хорошая идея. взял на заметку.

fwrite($f, pack('a'. $maxnamelen , $data[$i] )); а вот эта штуковина не раздует слишком файл?

если например имя одно 3 символа. а другое 32. то он забьет чем эти пространства? дополнит 3 до 32 чем? 

надо попробовать

дополнит нулл байтами, раздует, но итоговая база вряд ли будет какой-то очень большой, как другой рабочий вариант, если боитесь, что не хватит места на хостинге - подготовьте два датафайла:

- один из них будет индексом, в нём будут идешниками номера записей, а значениями, с какого по какой байт во втором датафайле находится содержимое

- второй - собственно содержимое, подряд, можно даже не паковать его, а просто подряд записывать

$f1 = fopen(__DIR__ . '/person_index.bin','wb+');
$f2 = fopen(__DIR__ . '/person_data.bin','wb+');
$from = 0;
for($i=0;$i<=$max;$i++)
{
        if(isset($data[$i]))
        {
                $to=$from+strlen($data[$i]);
                fwrite($f1, pack('N', $from ).pack('N', $to ));
                fwrite($f2, $data[$i]);
                $from = $to;
        }
        else
        {
                fwrite($f1, pack('N', 0 ).pack('N', 0 ));
        }
}
fclose($f1);
fclose($f2);
W1
На сайте с 22.01.2021
Offline
289
#27
Если уж такое резкое неприятие баз данных, то довольно неплохой вариант предложил Shelton724. Метод подходит и для буквенных ключей - данные сохраняются в текстовых файлах, имена которых формируются исходя, например, из первого символа буквенного ключа.
Работает по скорости быстрее sypexgeo - Веб-строительство - Сайтостроение
Работает по скорости быстрее sypexgeo - Веб-строительство - Сайтостроение
  • 2023.07.10
  • searchengines.guru
А если уйти от использования функции json , которая потребляет много памяти. что ваши распакованные данные займут тот же объем памяти. для работы с большими объемами данных придуманы базы данных. Если надо просто поместите бд файл в память и все будет работать еще быстрее
Мой форум - https://webinfo.guru –Там я всегда на связи
WS
На сайте с 01.11.2008
Offline
136
#28

так более оптимально, можно записывать не с какого по какой байт, а с какого байта и длину (C - до 256):

$f1 = fopen(__DIR__ . '/person_index.bin','wb+');
$f2 = fopen(__DIR__ . '/person_data.bin','wb+');
$from = 0;
for($i=0;$i<=$max;$i++)
{
        if(isset($data[$i]))
        {
                $len=strlen($data[$i]);
                fwrite($f1, pack('N', $from ).pack('C', $len ));
                fwrite($f2, $data[$i]);
                $from+= $len;
        }
        else
        {
                fwrite($f1, pack('N', 0 ).pack('N', 0 ));
        }
}
fclose($f1);
fclose($f2);

а чтобы прочитать потом по идешнику $id, умножаем $id на 5 (N 4 байта + C 1 байт), читаем индекс с нужного места, 5 байт, определяем с какого байта надо читать датафайл и длину и читаем

ps: при использовании N - максимальный размер датафайла с данными, около 4 гигов

1 23

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий