Flat |
Отправлено: 27 июля 2018 — 14:27
|
Full Member
Покинул форум
Сообщений всего: 187
Дата рег-ции: Май 2018
Откуда: Красноярский край
Репутация: 14
|
1Bot пишет:Есть вопрос как хранить структуры с переменным числом полей, наподобие ассоциативных массивов?
Думал об этом. Вот в реляционных базах, кстати, не используются многомерные представления в одной и той же таблице. Там используют ссылки на отдельные таблицы. Почему бы не поступить также? Можно, конечно, и эмулировать многомерные массивы таким примерно образом:
123|1|igor|ссылка1&ссылка2&ссылка3&ссылка4|следующее поле
Здесь четвёртое поле представляет из себя массив каких-то, например, ссылок, которые разделены другим, отличным от | знаком, в данном случае &. Парсить это очень легко. Если массив превышает определённую длину, то расширяем его вышеописанным образом.
Так что, возможен любой вариант.
1Bot пишет:Еще вопрос - как редактировать/удалять записи из такой структуры?
На данный момент вот такие соображения.
Например имеем базу с пользователями. Если надо удалить пользователя из базы, то возможны три варианта:
1) Если в каждой записи сделать дополнительное поле удалён/неудалён, то при удалении пользователя просто помечаем "удалён", а следующего зарегеного пользователя помещаем на место удалённого и присваеваем ему тот же номер.
2)Последовательно сдвигаем остаток базы с затиранием этой записи. Следующего зарегеного добавляем в конец базы.
3) Ничего не делаем(не удаляем физически).
По первому варианту.
Тут возможно следующее: если имеем несколько записей одного пользователя, а новый не совпадает со старым, то придётся как-то сдвинуть или расширить остаток базы.
Второй вариант более предпочтителен. Ведь удаляем мы сообщения или юзеров не часто, поэтому не важен небольшой оверхэд при сдвиге элементов. Если сдвигать по одной записи, то это и безопасно, ибо если на сервере произойдёт сбой, то мы, по крайней мере, потеряем единственную запись. Если же сдвинуть остаток целиком, то мы потеряем этот остаток. Сдвиг даже большого числа записей происходит за приемлемое время. Тем более, что обычно удаляются новые юзеры или относительно новые сообщения, которые находятся в конце(внизу) базы. Поэтому эта операция довольно быстра.
Правда в этом варианте номера удалённых пользователей больше не используются..(Отредактировано автором: 27 июля 2018 — 14:28) |
|
|
Flat |
Отправлено: 28 июля 2018 — 10:30
|
Full Member
Покинул форум
Сообщений всего: 187
Дата рег-ции: Май 2018
Откуда: Красноярский край
Репутация: 14
|
1Bot пишет:Удаленные записи/части записей лучше помечать как удаленные, фактически оставляя удаленные блоки без изменений.
Согласен. Всё же, частый сдвиг - небезопасен.
1Bot пишет:Реальную очистку производить по запросу VACUUM (в СУБД так и происходит).
Да, правильно. По необходимости вакуумируем через определённые промежутки времени. Если база большая, а лимит работы скрипта на сервере небольшой, то можно программно растянуть процесс вакуумирования, то есть при каждом новом запросе вакуумируем по частям.
1Bot пишет:При редактировании записи с текстом, если длина не увеличилась, то перезаписать на то же место
Правильно. Один ум хорошо, а два лучше. Даже если после редактирования сообщения текст уменьшится, то оставляем как есть, ничего не сдвигая. Это правильное решение, спасибо что навели. Базу лучше не трогать, пусть себе лежит, как лежит.
1Bot пишет:если увеличилась, то пометить текущую запись как удаленную и записать новую запись в конец файла.
Если это последняя запись в файле, то также переписываем.
Такс, а тут уже проблемы.. Ведь наша база, как предполагается должна быть упорядочена, например по id сообщения, то есть в конце будут самые последние сообщения, так мы их и выводим. Если записать отредактированное сообщение в конец файла, то порушится принцип упорядочености, и уже будет неприменим бинарный(двоичный) поиск по такой базе, то есть пропадёт основное её преимущество. В этом случае придётся применить некий принцип, который кстати используется при работе с файловыми системами и в базах данных.
Часть, которая влезает в редактируемое сообщение мы помещаем на место старого, а остаток, который не влезает, добавляем в конец файла, в запись, в которой в первом поле, где находится номер сообщения, записываем признак, того, что эта запись является продолжением другой записи, которая, в свою очередь, находится в другом месте, то есть, что данная запись разрывна. Например добавляем букву r в начало поля id:
r123|igor|привед медвед, это сообщение.
По букве r мы поймём, что это продолжение записи под номером 123 и не будем учитывать её при поиске по базе.
В первой же записи придётся записать индекс записи продолжения, для чего выделить своё поле. Такое поле будет и в записи продолжения, по которому мы поймём где искать дальнейшее продолжение. Это как в файловой системе, например такая система была в DOS. Да и в cqlite вроде используется.
Такая система несколько более сложная, однако позволит избавится о частого сдвига элементов.
1Bot пишет:Произвольную структуру в записи можно хранить в виде текста (использовать сериализацию или json).
Тоже интересное предложение. Например в тех же ссылках могут быть символы-разделители, что неприемлемо. Поэтому вы правы, если имеем многомерную структуру, то её лучше загнать в поле в json или каком-либо другом общепринятом виде, например csv или сериализовать.(Отредактировано автором: 28 июля 2018 — 10:33) |
|
|
Flat |
Отправлено: 29 июля 2018 — 01:58
|
Full Member
Покинул форум
Сообщений всего: 187
Дата рег-ции: Май 2018
Откуда: Красноярский край
Репутация: 14
|
Итак, вот что я решил..
Делать вменяемую СУБД возможно, но на это уйдёт куча времени, да и база будет недружелюбна к простым пользователям, ибо сообщения будут разбиваться на куски, которые к тому же будут валяться в разных местах файла.. Просто есть уже cqlite, зачем изобретать велосипеды.. Таким образом мы уходим от в общем-то здравой концепции exbb, которой необходимо придерживаться, иначе это уже будет совершенно другой форум..
Итак, оставляем концепцию формата хранения типа:
123|1|igor|следующее поле
То есть без сериализации. Это сохранит нам много нервов и дискового пространства.
Далее, в папке members в каждом файле сохраняем по 100 пользователей. Это даст нам постоянную высокую(ибо файл то небольшой) скорость загрузки даже при большом числе пользователей(несколько сот тысяч), а также избегаем потери дискового пространства из-за страничной организации памяти в современных ОС.
Также это обеспечит нам простой механизм изменение полей записей. К тому же это позволит нам иметь базу, в которой АБСОЛЮТНО(до самого последнего символа) отсутствует лишнее пространство. Если сообщение имеет определённую длину, то оно будет иметь ту же длину в файле, при этом ничего делить не потребуется, сообщение будет цельное, а также легко редактируемое.
Вчера написал функцию, проверки есть ли такой пользователь в базе или нет имея в виду новый формат файловой организации. Извините, если кому внушил ложные надежды, но мне нужен форум, который устраивал бы лично меня, а там уж кому нужно будет использовать мои наработки или подключится к его развитию.(Отредактировано автором: 29 июля 2018 — 02:01) |
|
|
Flat |
Отправлено: 30 июля 2018 — 08:29
|
Full Member
Покинул форум
Сообщений всего: 187
Дата рег-ции: Май 2018
Откуда: Красноярский край
Репутация: 14
|
Чувствую, последнее предложение ни у кого энтузиазма не вызывает..
Хорошо, - оставляем структуру папки members, как сейчас, то есть один файл на пользователя, но структуру записи делаем такую:
return array('id'=>1 ,'name'=>2,'pass'=>'21232f297a57a5a743894a0e4a801fc3');
Об этом я писал выше. Как видно здесь я избавился от лишних пробелов и переводов строки, которые оставляет функция var_export. Пусть занимает столько же места что и сериализация, однако место и так пропадает, и выделяется по сути с запасом на страницу памяти, так что ничего страшного. Зато легко сохранять многомерные структуры и база легко читаема и изменяема вручную. Не будем революционизировать движок. оставим концепцию в сохранности. Так будет легче конвертировать. Изменим общую структуру движка, сделав её более модульной. На том и порешили?
Написал новую более продвинутую функцию удаления непустой директории, а также функцию добавления в базу и функцию чтения из базы, которые позволяют уйти от проблемы обнуления. Юрий говорил, что проблема снята, однако судя по старым функциям проблема осталась на прежнем месте.(Отредактировано автором: 30 июля 2018 — 08:30) |
|
|
Flat |
Отправлено: 16 августа 2018 — 10:53
|
Full Member
Покинул форум
Сообщений всего: 187
Дата рег-ции: Май 2018
Откуда: Красноярский край
Репутация: 14
|
1Bot пишет: как Ваши успехи с файлами прямого доступа?
Постом выше я писал:
Цитата:Чувствую, последнее предложение ни у кого энтузиазма не вызывает..
Однако идею не оставил. Похоже, что надо будет предусмотреть оба варианта: один на файлах прямого доступа, а другой традиционный подход - один файл-один пользователь. Соблазн велик, что ни говори.. Да это и правильно так сделать, одним словом: по-компьютерному, так как и должно быть.. Но сейчас я был занят авторизацией. Авторизация практически готова. Та что в движке, меня не устраивает. Там идёт раздельная обработка разных состояний, в зависимости от включённости кук у пользователя, наличия "старой" сессии или "новой" и т.п. Головной модуль, через который подключаются другие, тоже практически готов.
Сейчас сделаю основные модули, типа: авторизация, входа/выхода с форума, регистрации, а затем всё остальное.
Знакомясь с кодом движка exbb некоторые вещи вызывают недоумение. Например, в файле fm.class.php есть функция _CheckBannedIP(). В ней есть такая строчка:
CODE: $banneddata = array_filter($this->_Read(FM_BANNEDIP),"Banned");
Функция array_filter вторым параметром принимает имя collback функции, которая вызывается на каждом элементе массива. Здесь указана функция "Banned", однако ни в одном файле движка я её так и не нашёл.. Выходит что IP не проверяется? Вэб-мастер может быть подскажет что тут не так. Вроде везде искал, в том числе и в новом 2.0 движке..
Далее, в файле common.php дублируется код
дубляж (Отобразить)CODE:if ($fm->exbb['installed'] === FALSE)
{
header("Location: ./install/index.php");
}
elseif (file_exists("./install/index.php"))
{
$fm->_Message($fm->LANG['MainMsg'],$fm->LANG['DelleteInstallDir']);
}
require('modules/mailer/_send.php');
if ($fm->exbb['board_closed'] && !(defined('IS_LOGIN') || defined('IS_ADMIN')))
{
$fm->_Message($fm->LANG['BoardClosed'],nl2br(strtr($fm->exbb['closed_mes'], array_flip(get_html_translation_table(HTML_SPECIALCHARS)))));
}
Что касается файлов прямого доступа.
Будет такой вариант, который подходит для больших форумов с огромным числом пользователей. Всё это реализовать несложно.(Отредактировано автором: 16 августа 2018 — 10:59) |
|
|
|