16. Flat - 13 июля 2018 — 12:27 - перейти к сообщению
Желательно бы ещё реализовать механизм настройки стиля отображения, как например это сделано в жж из админки. Чтобы не лазить по коду, а менять всё через центр.
17. Flat - 16 июля 2018 — 12:03 - перейти к сообщению
Flat пишет:
Текстовая база предполагается будет иметь такой вид:
<?die;?>$arr=array (
'id' => 1,
'name' => 'admin',
'pass' => 'jfjdkfvslklak84j4wyff7dhe7dhe'
'mail' => 'hhhhh@mail.ru',
array (
0 => 1
),
);
<?die;?>$arr=array (
'id' => 1,
'name' => 'admin',
'pass' => 'jfjdkfvslklak84j4wyff7dhe7dhe'
'mail' => 'hhhhh@mail.ru',
array (
0 => 1
),
);
Если использовать такой вид:
CODE:
<?php
if (!defined('IN_EXBB') ) die('Hack attempt!') ;
return array
(
'id' => 1,
'name' => 'admin',
'pass' => 'jfjdkfvslklak84j4wyff7dhe7dhe'
'mail' => 'hhhhh@mail.ru'
);
?>
if (!defined('IN_EXBB') ) die('Hack attempt!') ;
return array
(
'id' => 1,
'name' => 'admin',
'pass' => 'jfjdkfvslklak84j4wyff7dhe7dhe'
'mail' => 'hhhhh@mail.ru'
);
?>
то отпадает необходимость в функции read, так как теперь файл подключаем просто:
$nameOfArray=include "datfile.php";
18. Flat - 21 июля 2018 — 11:16 - перейти к сообщению
1Bot пишет:
До сих пор сложно разрабатывать модули (нет описания интерфейсов взаимодействия ядра и модуля, тут полиморфизм ООП был бы очень кстати), чтобы их было легко интегрировать в админку и в основной форум.
Вот не согласен, что обязательно нужен полиморфизм ООП и вообще ООП. Помните как всё начиналось? Был простой и относительно понятный скрипт. Его можно было понять начинающему в PHP. Это была его фишка, как и то, что он имел файловую базу. Ввели ООП, пусть даже "недоООП", однако, чтобы понимать код, теперь нужно быть программистом, программистом-админом, а не просто админом с начальными навыками PHP. Но это всё лирика, а давайте о модульности.
Если кто остался в трезвом уме и твёрдой памяти, ибо прошло уже много лет, и помнит ещё то, что Юрий говорил о модульности в данном движке. Он говорил - чтобы написать какое-то расширение к exbb, необходимо изучить ВЕСЬ код exbb! Однако мало тех, кто осилил это. Многие говорили в том же духе и желали иметь такую систему, в которой можно было бы одним кликом устанавливать модули.
Чтобы этого добиться необходимо написать абсолютно новое ядро, о чём говорил Юрий. Также он писал, что одному это не по силам, ибо посмотрите сколько программистов работают над импортными популярными движками. По силам-не по силам, это ещё тот вопрос..
Создание нового ядра назрело и перезрело. Развитие exbb остановилось потому, что невозможно вменямо писать для него модули. Форк, который поддерживает вебмастер это другой зверь, традиционный, и скорее всего тупиковый. Это попытка разукрасить давно умершего..
К чему я пришёл после долгих раздумий.
1) Должна быть тотальная модульность.. Такая, при которой возможно будет в один клик заменить даже само ядро системы.. Цель: при установке модулей не лазить в код, а просто запускать инсталлятор. Он сделает всю работу за нас.
2) Для написания модуля не нужно будет знать весь код движка, а только некоторые правила создания модуля и соглашения.
3) Всё в движке должно быть строго одинаково и сделано по аналогии со всеми остальными. Что это значит? Каждый модуль состоит из 4 главных файлов:
1. install.php - инсталлятор модуля. Запускается в один клик и устанавливает модуль в систему;
2. uninstall.php - деинсталятор модуля. Удаляет модуль из системы;
3. index.php - головной файл модуля, который его запускает при работе;
4. config.php - файл конфигурации модуля. В нём прописаны зависимости модуля, какие компоненты он запускает, версию, и др. параметры;
Остальные файлы и папки опционные. Если данный модуль имеет собственные компоненты, то создаётся отдельная папка компонентов, в которой будет такая же структура, как и в головном модуле.
Как происходит работа? В ядре системы находится функция-загрузчик. Её услугами пользуется каждый модуль системы. Она сканирует конфигурационный файл и подключает те модули, которые в нём прописаны. Так происходит в каждом модуле.
Система становится логичной и понятной. Каждый делает своё дело и никому не мешает. Так мне это представляется.
19. Flat - 22 июля 2018 — 10:28 - перейти к сообщению
Или вместо конфигурационных файлов в каждом модуле, ввести некий общий реестр всех модулей в системе, некую общую память системы по аналогии с конфигом форума. Это позволит избавится от многочисленных инклюдов. Core-модуль загружает реестр, а все остальные модули пользуются общим реестром. Это как в операционной системе, где есть свой общий реестр - общая память системы. Форумный движок по сути и есть операционная система в миниатюре. Должно быть микроядро и компоненты вокруг него, а также реестр. Больше по сути ничего не нужно. Каждый модуль работает с другими через общий реестр и интерфейс, который предоставляет каждый модуль..
20. Flat - 24 июля 2018 — 10:25 - перейти к сообщению
Чем больше знакомлюсь с кодом, тем больше возникает вопросов. Особенно что касается основы основ - работы с базой данных.
В коде используются велосипеды, которые давно решены штатными средствами.
Структуры массивов-таблиц непродуманны.
Юрий предлагал сделать текстовую базу на прямом доступе. Это позволило бы иметь форум, который не тормозил бы и при миллионе пользователей, причём без всяких "мускулов". Однако он предлагал этот вариант на платной основе, видимо хотел так заработать. Зарабатывать надо на модах и услугах пользователям, а не продавая готовый двиг, который всё равно отпиратят.
У меня есть наработки по такой базе.
Кто-то может сказать: зачем это, если есть sqlite? Скажу: сейчас модуль sqlite работает только через драйвер pdo, таким образом полностью "кинуты" те пользователи, кои хотят сидеть на процедурщине. Дискриминация на лицо, а что будет дальше..
Далее, представьте себе ситуацию, когда на сервере происходит сбой а ваша база повреждена. "Вылечить" базу sqlite трудно даже продвинутым программерам, а обычным юзверям вообще не под силу, ибо она не текстовая а бинарная со многими зависимостями..
Так что не вариант.
Нужна текстовая база прямого доступа.
В коде используются велосипеды, которые давно решены штатными средствами.
Структуры массивов-таблиц непродуманны.
Юрий предлагал сделать текстовую базу на прямом доступе. Это позволило бы иметь форум, который не тормозил бы и при миллионе пользователей, причём без всяких "мускулов". Однако он предлагал этот вариант на платной основе, видимо хотел так заработать. Зарабатывать надо на модах и услугах пользователям, а не продавая готовый двиг, который всё равно отпиратят.
У меня есть наработки по такой базе.
Кто-то может сказать: зачем это, если есть sqlite? Скажу: сейчас модуль sqlite работает только через драйвер pdo, таким образом полностью "кинуты" те пользователи, кои хотят сидеть на процедурщине. Дискриминация на лицо, а что будет дальше..
Далее, представьте себе ситуацию, когда на сервере происходит сбой а ваша база повреждена. "Вылечить" базу sqlite трудно даже продвинутым программерам, а обычным юзверям вообще не под силу, ибо она не текстовая а бинарная со многими зависимостями..
Так что не вариант.
Нужна текстовая база прямого доступа.
21. - 25 июля 2018 — 10:28 - перейти к сообщению
Flat пишет:
Делитесь - будем пробовать внедрять.
У меня есть наработки по такой базе.
22. Flat - 25 июля 2018 — 13:01 - перейти к сообщению
NordWest пишет:
Делитесь - будем пробовать внедрять.
Пока нечем делится, вот в чём дело. Есть функция бинарного поиска по такой базе. Работает, ну, если не сказать быстро, то ничего не сказать: ураган. Бинарный поиск нужен при упорядоченной по какому либо признаку записей базы, а не по индексу. Если по индексу, то сложно реализовать удаление записей. Есть понимание как это должно работать без излишних сложностей. Сейчас занимаюсь дополнительным тестированием некоторых моментов. Затем сразу приступаю к созданию первого модуля - db, по работе с базой. Придётся полностью отдать себя работе, иначе ничего не выйдет.
Почему я бросил эту идею с базой такого вида:
'id' => 1,
'name' => 'admin', и т.д.
Сравнил с базой такого вида:
1|admin
и получилось, что в среднем перерасход памяти вылетает в 2-5 раз. Вот не понимаю, зачем держать весь этот мусор в базе? База должна иметь только то, что должна, ничего лишнего. Если у вас хостинг резиновый и денег куры не клюют, то можно оставить всё как есть, но что-то мне подсказывает, что цены тоже не стоят на месте, и лучше иметь компактную базу, которую легко бэкапить, чем постоянно таскать с собой воз ненужного мусора.
Такую базу можно править в ручном режиме. Правда пользуясь при этом некоторыми соглашениями. Чтобы база работала быстро длина записей выбрана постоянной. Для хранения сообщений пользователей записи клонируются под таким же id, это позволит не перерасходовать в пустую дисковое пространство. Потом покажу код.
23. - 25 июля 2018 — 14:02 - перейти к сообщению
Вы можете пояснить, что такое "текстовая база на прямом доступе"?
Показать как это работает на простейшем примере?
Показать как это работает на простейшем примере?
24. - 25 июля 2018 — 15:51 - перейти к сообщению
Вот это жара пошла! Надеюсь, у Flat не пропадёт интузиазм и в итоге он не слиняет, как предшествующие товарищи ;о)
25. Flat - 26 июля 2018 — 10:27 - перейти к сообщению
NordWest пишет:
Вы можете пояснить, что такое "текстовая база на прямом доступе"?
Сейчас популярно обьясню))
Например имеем такую базу данных, в которой каждая строка это одна запись, а отдельные поля записи отделены каким-либо редко используемым знаком. Зачастую для этой цели используется знак |(вертикальная черта):
0000001| admin|password|ad@kuku.com|ad
0000002| masha|password|gg@zuzu.com|me
0000003|grisha|password|ff@bubu.com|me
и т.д
Естественно, что вертикальную черту в текстах необходимо заменить на html сущности.
Каждое поле имеет определённую длину, которая прописана в скрипте, а общая длина записи постоянна.
Чтобы получить отдельную запись или отдельное поле при прямом доступе, ненужно качать всю базу в память, а необходимо, просто напросто, подвести считывающую головку(виртуальную, ибо сейчас уже используют твёрдотельные накопители) непосредственно к записи и считать её в память. Делается это очень просто. Вчера написал функцию, которая ищет в такой базе отдельную запись и считывает какое-то её поле. Эта функция не предназначена для форумного движка, это просто тестовая функция. Она ищет по принципу прямого перебора(а не бинарного поиска) элементов, используя принцип прямого доступа:
CODE:
function find($fl, $val, $field, $fieldLen)
{
$Len=156;
$numFields=100000;
if(!($f = fopen($fl, "rb")))die();
flock ($f,LOCK_SH);
$buf='';
for($s=0; $s<$numFields; ++$s)
{
fseek($f, $s*$Len+$field, SEEK_SET);
$buf=fread($f, $fieldLen);
if(strcmp($buf, $val)==0)
{
flock ($f,LOCK_UN);
fclose($f);
return true;
}
}
flock ($f,LOCK_UN);
fclose($f);
return false;
}
{
$Len=156;
$numFields=100000;
if(!($f = fopen($fl, "rb")))die();
flock ($f,LOCK_SH);
$buf='';
for($s=0; $s<$numFields; ++$s)
{
fseek($f, $s*$Len+$field, SEEK_SET);
$buf=fread($f, $fieldLen);
if(strcmp($buf, $val)==0)
{
flock ($f,LOCK_UN);
fclose($f);
return true;
}
}
flock ($f,LOCK_UN);
fclose($f);
return false;
}
Проверял скорость на прямом переборе потому, что это будет необходимо при удалении и редактировании записей. Создал базу из записей по 156 байтов, записей 100 000, вес базы 15 мегабайт с лишним. Так вот, скорость поиска последнего элемента такой базы составила 0,2 секунды. База в 1 миллион записей будет иметь скорость 2 сек. Это в 2 раза меньше, чем качать всю базу в память посредством функции file, а потом разбивать её при помощи explode.
Затем протестировал бинарный поиск по такой базе, при помощи моей функции бинарного поиска:
CODE:
function DbFindRecord($fl, $login, $recordLen, $numRecords)
{
global $dbLastFind;
if(!($f = fopen($fl, "rb")))die();
flock ($f,LOCK_SH);
$low = 0; $mid=0; $midval=''; $ind=0; $c=0;
$high = $numRecords-1;
while($low <= $high)
{
$mid = (int)($low + (($high - $low) / 2));
$ind = (int)($mid*$recordLen);
fseek($f, $ind, SEEK_SET);
$midVal = fread( $f, 2);
$c=strcmp($midVal, $login);
if ( $c < 0)
{$low = $mid + 1;}
else if ($c > 0)
{$high = $mid - 1;}
else
{
flock ($f,LOCK_UN);
fclose($f);
$dbLastFind=$ind;
return $ind;
}
}
$dbLastFind=$ind;
flock ($f,LOCK_UN);
fclose($f);
return -1;
}
{
global $dbLastFind;
if(!($f = fopen($fl, "rb")))die();
flock ($f,LOCK_SH);
$low = 0; $mid=0; $midval=''; $ind=0; $c=0;
$high = $numRecords-1;
while($low <= $high)
{
$mid = (int)($low + (($high - $low) / 2));
$ind = (int)($mid*$recordLen);
fseek($f, $ind, SEEK_SET);
$midVal = fread( $f, 2);
$c=strcmp($midVal, $login);
if ( $c < 0)
{$low = $mid + 1;}
else if ($c > 0)
{$high = $mid - 1;}
else
{
flock ($f,LOCK_UN);
fclose($f);
$dbLastFind=$ind;
return $ind;
}
}
$dbLastFind=$ind;
flock ($f,LOCK_UN);
fclose($f);
return -1;
}
, и оказалось , что скорость увеличилась где-то в 500 раз.. То есть не 0,2 сек., а 0,2/500 = тут сами подсчитайте на калькуляторе сколько это будет: просто один миг.. То есть поиск по миллионной базе займёт доли секунды..
Эта функция тоже тестовая и будет переделана.
Guyver пишет:
Надеюсь, у Flat не пропадёт интузиазм и в итоге он не слиняет, как предшествующие товарищи ;о)
Интузиазм не пропадёт. Будем надеяться, что всё будет хорошо. Что не отключат электроэнергию, или интернет, или с компом вся будет в порядке, да и со здоровьем.))
26. 1Bot - 26 июля 2018 — 19:59 - перейти к сообщению
Что сказать, сами придумываем велосипеды, которые уже давно ездят в существующих СУБД.
Экскурс в историю баз данных и их проектирования (чтобы не выдумывать велосипеды)
Экскурс посвящен внутренней структуре реляционных баз данных
Поля таблицы могут определять так называемые ключи и индексы.
Ключ — это комбинация нескольких полей, данные в которых однозначно определяют запись Таблицы.
Ключи бывают простыми и сложными (составными).
Простой ключ — это ключ, состоящий из одного поля.
Сложный или составной ключ включает в себя данные нескольких полей.
Данные простого ключа должны быть уникальными.
Составной ключ может иметь повторы в отдельных полях, но не во всех одновременно.
Соответственно поля, по которым строится ключ, называются ключевыми полями.
В каждой таблице может быть только один ключ.
Ключ иногда называют первичным ключом или главным индексом.
Для чего же служит ключ? Прежде всего, для обеспечения однозначного определения записей таблицы.
Кроме того, ключ предназначен для более быстрого выполнения запросов к базе данных.
По ключевым полям организуется связь между таблицами базы данных.
У ключа есть еще много других функций, они будут объясняться по мере изложения.
Сведения о ключе таблицы могут храниться как вместе с данными таблицы, так и в отдельном файле.
Этот файл имеет такое же имя, что и файл таблицы, но другое расширение.
Например, в базе данных Microsoft Access информация о ключе содержится вместе с данными в одном файле, который имеет расширение .MDB.
А Paradox выделяет для информации о ключе отдельный файл с расширением .РХ.
Ключевой файл содержит значения ключа, которые располагаются в определенном порядке.
Для каждого из значений ключа имеется уникальная ссылка, которая указывает местоположение соответствующей записи в файле таблицы.
Таким образом, во время поиска в таблице будет выполнен прямой доступ к необходимой записи на основании упорядоченных значений ключа, а не последовательный перебор записей таблицы.
Тем самым значительно увеличивается скорость доступа к искомой информации, хотя в результате размер базы может сильно вырасти (возможно, даже в два раза) за счет хранения дополнительной ключевой информации.
Ключевые поля вам придется определять самостоятельно, поэтому следуйте представленным ниже правилам, которые помогут достаточно эффективно выбрать эти поля:
- ключевым полем не может быть поле, содержащее графику, или поле типа memo, включающее в себя комментарии;
- нежелательно выбирать в качестве ключевого поля поле, содержащее фамилии людей, так как существует большая вероятность включения в базу данных однофамильцев и при этом будет нарушена уникальность ключа;
- если вы используете поле, по которому производится нумерация записей (например, автоинкрементное поле), то имеет смысл сделать его ключевым, поскольку номер записи будет уникальным;
- старайтесь задавать ключевые поля в каждой таблице базы данных, даже если их присутствие на первый взгляд не является необходимым.
- ключ не должен содержать поля, которые можно удалить, не нарушив при этом уникальности ключа;
Индекс - это комбинация нескольких полей, которые служат для быстрого доступа к необходимой информации.
Основным отличием индекса от ключа является то, что поля индекса могут определять не одну, а несколько записей.
Таким образом, индекс не всегда однозначно определяет запись в таблице базы данных.
Индексы так же, как и ключи, могут быть простыми и составными.
Простой индекс состоит из одного поля, а составной — из нескольких полей.
Поля, по которым строится индекс, называют индексными полями.
Процесс создания индекса называется индексированием таблицы.
Индекс используется для увеличения скорости доступа к данным, для быстрой сортировки данных таблицы.
В отличие от ключа, который является уникальным в каждой таблице, индексов в ней может быть несколько.
Это в первую очередь необходимо для быстрой сортировки по нужному полю или полям.
Если эти поля проиндексированы, то сортировка по ним будет выполнена значительно быстрее, чем по обычным полям.
В любой момент времени можно активировать любой из индексов таблицы.
Именно по активному (текущему) индексу обычно будет выполняться сортировка записей таблицы.
Следует, однако, заметить, что, несмотря на наличие нескольких индексов, таблица может не иметь текущего индекса.
Вообще говоря, поведение индексов и ключей зависит от типа используемой базы данных.
Так, например, в таблицах Paradox ключ автоматически является главным индексом, который не имеет имени.
В то же время в таблицах dBase ключ в принципе не создается, вместо него используется один из индексов.
Но в общем случае ключевые поля обычно автоматически индексируются.
ВНИМАНИЕ: Процесс создания ключа в ряде случаев может привести к неожиданным результатам.
Например, при создании ключа в таблице базы данных Paradox будут автоматически отсортированы записи по значениям ключа.
Экскурс в историю баз данных и их проектирования (чтобы не выдумывать велосипеды)
Экскурс посвящен внутренней структуре реляционных баз данных
Поля таблицы могут определять так называемые ключи и индексы.
Ключ — это комбинация нескольких полей, данные в которых однозначно определяют запись Таблицы.
Ключи бывают простыми и сложными (составными).
Простой ключ — это ключ, состоящий из одного поля.
Сложный или составной ключ включает в себя данные нескольких полей.
Данные простого ключа должны быть уникальными.
Составной ключ может иметь повторы в отдельных полях, но не во всех одновременно.
Соответственно поля, по которым строится ключ, называются ключевыми полями.
В каждой таблице может быть только один ключ.
Ключ иногда называют первичным ключом или главным индексом.
Для чего же служит ключ? Прежде всего, для обеспечения однозначного определения записей таблицы.
Кроме того, ключ предназначен для более быстрого выполнения запросов к базе данных.
По ключевым полям организуется связь между таблицами базы данных.
У ключа есть еще много других функций, они будут объясняться по мере изложения.
Сведения о ключе таблицы могут храниться как вместе с данными таблицы, так и в отдельном файле.
Этот файл имеет такое же имя, что и файл таблицы, но другое расширение.
Например, в базе данных Microsoft Access информация о ключе содержится вместе с данными в одном файле, который имеет расширение .MDB.
А Paradox выделяет для информации о ключе отдельный файл с расширением .РХ.
Ключевой файл содержит значения ключа, которые располагаются в определенном порядке.
Для каждого из значений ключа имеется уникальная ссылка, которая указывает местоположение соответствующей записи в файле таблицы.
Таким образом, во время поиска в таблице будет выполнен прямой доступ к необходимой записи на основании упорядоченных значений ключа, а не последовательный перебор записей таблицы.
Тем самым значительно увеличивается скорость доступа к искомой информации, хотя в результате размер базы может сильно вырасти (возможно, даже в два раза) за счет хранения дополнительной ключевой информации.
Ключевые поля вам придется определять самостоятельно, поэтому следуйте представленным ниже правилам, которые помогут достаточно эффективно выбрать эти поля:
- ключевым полем не может быть поле, содержащее графику, или поле типа memo, включающее в себя комментарии;
- нежелательно выбирать в качестве ключевого поля поле, содержащее фамилии людей, так как существует большая вероятность включения в базу данных однофамильцев и при этом будет нарушена уникальность ключа;
- если вы используете поле, по которому производится нумерация записей (например, автоинкрементное поле), то имеет смысл сделать его ключевым, поскольку номер записи будет уникальным;
- старайтесь задавать ключевые поля в каждой таблице базы данных, даже если их присутствие на первый взгляд не является необходимым.
- ключ не должен содержать поля, которые можно удалить, не нарушив при этом уникальности ключа;
Индекс - это комбинация нескольких полей, которые служат для быстрого доступа к необходимой информации.
Основным отличием индекса от ключа является то, что поля индекса могут определять не одну, а несколько записей.
Таким образом, индекс не всегда однозначно определяет запись в таблице базы данных.
Индексы так же, как и ключи, могут быть простыми и составными.
Простой индекс состоит из одного поля, а составной — из нескольких полей.
Поля, по которым строится индекс, называют индексными полями.
Процесс создания индекса называется индексированием таблицы.
Индекс используется для увеличения скорости доступа к данным, для быстрой сортировки данных таблицы.
В отличие от ключа, который является уникальным в каждой таблице, индексов в ней может быть несколько.
Это в первую очередь необходимо для быстрой сортировки по нужному полю или полям.
Если эти поля проиндексированы, то сортировка по ним будет выполнена значительно быстрее, чем по обычным полям.
В любой момент времени можно активировать любой из индексов таблицы.
Именно по активному (текущему) индексу обычно будет выполняться сортировка записей таблицы.
Следует, однако, заметить, что, несмотря на наличие нескольких индексов, таблица может не иметь текущего индекса.
Вообще говоря, поведение индексов и ключей зависит от типа используемой базы данных.
Так, например, в таблицах Paradox ключ автоматически является главным индексом, который не имеет имени.
В то же время в таблицах dBase ключ в принципе не создается, вместо него используется один из индексов.
Но в общем случае ключевые поля обычно автоматически индексируются.
ВНИМАНИЕ: Процесс создания ключа в ряде случаев может привести к неожиданным результатам.
Например, при создании ключа в таблице базы данных Paradox будут автоматически отсортированы записи по значениям ключа.
27. 1Bot - 26 июля 2018 — 20:20 - перейти к сообщению
Flat пишет:
Проверял скорость на прямом переборе потому, что это будет необходимо при удалении и редактировании записей. Создал базу из записей по 156 байтов, записей 100 000, вес базы 15 мегабайт с лишним. Так вот, скорость поиска последнего элемента такой базы составила 0,2 секунды. База в 1 миллион записей будет иметь скорость 2 сек. Это в 2 раза меньше, чем качать всю базу в память посредством функции file, а потом разбивать её при помощи explode.
Затем протестировал бинарный поиск по такой базе, при помощи моей функции бинарного поиска:
...
, и оказалось , что скорость увеличилась где-то в 500 раз.. То есть не 0,2 сек., а 0,2/500 = тут сами подсчитайте на калькуляторе сколько это будет: просто один миг.. То есть поиск по миллионной базе займёт доли секунды..
Эта функция тоже тестовая и будет переделана.
Затем протестировал бинарный поиск по такой базе, при помощи моей функции бинарного поиска:
...
, и оказалось , что скорость увеличилась где-то в 500 раз.. То есть не 0,2 сек., а 0,2/500 = тут сами подсчитайте на калькуляторе сколько это будет: просто один миг.. То есть поиск по миллионной базе займёт доли секунды..
Эта функция тоже тестовая и будет переделана.
Приведу для сравнения примеры выборок из таблицы СУБД mysql c 2 242 208 записями (общим размером 2 ГБ), где каждая запись состоит из 47 полей
CODE:
CREATE TABLE `updated` (
`ID` INT(15) UNSIGNED NOT NULL AUTO_INCREMENT,
`Title` VARCHAR(2000) NULL DEFAULT '',
`VolumeInfo` VARCHAR(100) NULL DEFAULT '',
`Series` VARCHAR(300) NULL DEFAULT '',
`Periodical` VARCHAR(200) NULL DEFAULT '',
`Author` VARCHAR(1000) NULL DEFAULT '',
`Year` VARCHAR(14) NULL DEFAULT '',
`Edition` VARCHAR(60) NULL DEFAULT '',
`Publisher` VARCHAR(400) NULL DEFAULT '',
`City` VARCHAR(100) NULL DEFAULT '',
`Pages` VARCHAR(100) NULL DEFAULT '',
`PagesInFile` INT(10) UNSIGNED NOT NULL DEFAULT '0',
`Language` VARCHAR(150) NULL DEFAULT '',
`Topic` VARCHAR(500) NULL DEFAULT '',
`Library` VARCHAR(50) NULL DEFAULT '',
`Issue` VARCHAR(100) NULL DEFAULT '',
`Identifier` VARCHAR(300) NULL DEFAULT '',
`ISSN` VARCHAR(9) NULL DEFAULT '',
`ASIN` VARCHAR(200) NULL DEFAULT '',
`UDC` VARCHAR(200) NULL DEFAULT '',
`LBC` VARCHAR(200) NULL DEFAULT '',
`DDC` VARCHAR(45) NULL DEFAULT '',
`LCC` VARCHAR(45) NULL DEFAULT '',
`Doi` VARCHAR(45) NULL DEFAULT '',
`Googlebookid` VARCHAR(45) NULL DEFAULT '',
`OpenLibraryID` VARCHAR(200) NULL DEFAULT '',
`Commentary` VARCHAR(10000) NULL DEFAULT '',
`DPI` INT(6) UNSIGNED NULL DEFAULT '0',
`Color` VARCHAR(1) NULL DEFAULT '',
`Cleaned` VARCHAR(1) NULL DEFAULT '',
`Orientation` VARCHAR(1) NULL DEFAULT '',
`Paginated` VARCHAR(1) NULL DEFAULT '',
`Scanned` VARCHAR(1) NULL DEFAULT '',
`Bookmarked` VARCHAR(1) NULL DEFAULT '',
`Searchable` VARCHAR(1) NULL DEFAULT '',
`Filesize` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0',
`Extension` VARCHAR(50) NULL DEFAULT '',
`MD5` CHAR(32) NULL DEFAULT '',
`Generic` CHAR(32) NULL DEFAULT '',
`Visible` CHAR(3) NULL DEFAULT '',
`Locator` VARCHAR(733) NULL DEFAULT '',
`Local` INT(10) UNSIGNED NULL DEFAULT '0',
`TimeAdded` TIMESTAMP NOT NULL DEFAULT '2000-01-01 07:00:00',
`TimeLastModified` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`Coverurl` VARCHAR(200) NULL DEFAULT '',
`Tags` VARCHAR(500) NULL DEFAULT '',
`IdentifierWODash` VARCHAR(300) NULL DEFAULT '',
PRIMARY KEY (`ID`),
UNIQUE INDEX `MD5` (`MD5`),
INDEX `Generic` (`Generic`) USING BTREE,
INDEX `VisibleTimeAdded` (`Visible`, `TimeAdded`) USING BTREE,
INDEX `TimeAdded` (`TimeAdded`) USING BTREE,
INDEX `Topic` (`Topic`(3)) USING BTREE,
INDEX `VisibleID` (`Visible`, `ID`) USING BTREE,
INDEX `VisibleTimeLastModified` (`Visible`, `TimeLastModified`, `ID`) USING BTREE,
INDEX `TimeLastModifiedID` (`TimeLastModified`, `ID`) USING BTREE,
INDEX `DOI_INDEX` (`Doi`) USING BTREE,
INDEX `Identifier` (`Identifier`),
FULLTEXT INDEX `Title` (`Title`),
FULLTEXT INDEX `Author` (`Author`),
FULLTEXT INDEX `Language` (`Language`),
FULLTEXT INDEX `Extension` (`Extension`),
FULLTEXT INDEX `Publisher` (`Publisher`),
FULLTEXT INDEX `Series` (`Series`),
FULLTEXT INDEX `Year` (`Year`),
FULLTEXT INDEX `Title1` (`Title`, `Author`, `Series`, `Publisher`, `Year`, `Periodical`, `VolumeInfo`),
FULLTEXT INDEX `Tags` (`Tags`),
FULLTEXT INDEX `Identifierfulltext` (`IdentifierWODash`)
)
COLLATE='utf8_general_ci'
ENGINE=MyISAM
AUTO_INCREMENT=2242208;
`ID` INT(15) UNSIGNED NOT NULL AUTO_INCREMENT,
`Title` VARCHAR(2000) NULL DEFAULT '',
`VolumeInfo` VARCHAR(100) NULL DEFAULT '',
`Series` VARCHAR(300) NULL DEFAULT '',
`Periodical` VARCHAR(200) NULL DEFAULT '',
`Author` VARCHAR(1000) NULL DEFAULT '',
`Year` VARCHAR(14) NULL DEFAULT '',
`Edition` VARCHAR(60) NULL DEFAULT '',
`Publisher` VARCHAR(400) NULL DEFAULT '',
`City` VARCHAR(100) NULL DEFAULT '',
`Pages` VARCHAR(100) NULL DEFAULT '',
`PagesInFile` INT(10) UNSIGNED NOT NULL DEFAULT '0',
`Language` VARCHAR(150) NULL DEFAULT '',
`Topic` VARCHAR(500) NULL DEFAULT '',
`Library` VARCHAR(50) NULL DEFAULT '',
`Issue` VARCHAR(100) NULL DEFAULT '',
`Identifier` VARCHAR(300) NULL DEFAULT '',
`ISSN` VARCHAR(9) NULL DEFAULT '',
`ASIN` VARCHAR(200) NULL DEFAULT '',
`UDC` VARCHAR(200) NULL DEFAULT '',
`LBC` VARCHAR(200) NULL DEFAULT '',
`DDC` VARCHAR(45) NULL DEFAULT '',
`LCC` VARCHAR(45) NULL DEFAULT '',
`Doi` VARCHAR(45) NULL DEFAULT '',
`Googlebookid` VARCHAR(45) NULL DEFAULT '',
`OpenLibraryID` VARCHAR(200) NULL DEFAULT '',
`Commentary` VARCHAR(10000) NULL DEFAULT '',
`DPI` INT(6) UNSIGNED NULL DEFAULT '0',
`Color` VARCHAR(1) NULL DEFAULT '',
`Cleaned` VARCHAR(1) NULL DEFAULT '',
`Orientation` VARCHAR(1) NULL DEFAULT '',
`Paginated` VARCHAR(1) NULL DEFAULT '',
`Scanned` VARCHAR(1) NULL DEFAULT '',
`Bookmarked` VARCHAR(1) NULL DEFAULT '',
`Searchable` VARCHAR(1) NULL DEFAULT '',
`Filesize` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0',
`Extension` VARCHAR(50) NULL DEFAULT '',
`MD5` CHAR(32) NULL DEFAULT '',
`Generic` CHAR(32) NULL DEFAULT '',
`Visible` CHAR(3) NULL DEFAULT '',
`Locator` VARCHAR(733) NULL DEFAULT '',
`Local` INT(10) UNSIGNED NULL DEFAULT '0',
`TimeAdded` TIMESTAMP NOT NULL DEFAULT '2000-01-01 07:00:00',
`TimeLastModified` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`Coverurl` VARCHAR(200) NULL DEFAULT '',
`Tags` VARCHAR(500) NULL DEFAULT '',
`IdentifierWODash` VARCHAR(300) NULL DEFAULT '',
PRIMARY KEY (`ID`),
UNIQUE INDEX `MD5` (`MD5`),
INDEX `Generic` (`Generic`) USING BTREE,
INDEX `VisibleTimeAdded` (`Visible`, `TimeAdded`) USING BTREE,
INDEX `TimeAdded` (`TimeAdded`) USING BTREE,
INDEX `Topic` (`Topic`(3)) USING BTREE,
INDEX `VisibleID` (`Visible`, `ID`) USING BTREE,
INDEX `VisibleTimeLastModified` (`Visible`, `TimeLastModified`, `ID`) USING BTREE,
INDEX `TimeLastModifiedID` (`TimeLastModified`, `ID`) USING BTREE,
INDEX `DOI_INDEX` (`Doi`) USING BTREE,
INDEX `Identifier` (`Identifier`),
FULLTEXT INDEX `Title` (`Title`),
FULLTEXT INDEX `Author` (`Author`),
FULLTEXT INDEX `Language` (`Language`),
FULLTEXT INDEX `Extension` (`Extension`),
FULLTEXT INDEX `Publisher` (`Publisher`),
FULLTEXT INDEX `Series` (`Series`),
FULLTEXT INDEX `Year` (`Year`),
FULLTEXT INDEX `Title1` (`Title`, `Author`, `Series`, `Publisher`, `Year`, `Periodical`, `VolumeInfo`),
FULLTEXT INDEX `Tags` (`Tags`),
FULLTEXT INDEX `Identifierfulltext` (`IdentifierWODash`)
)
COLLATE='utf8_general_ci'
ENGINE=MyISAM
AUTO_INCREMENT=2242208;
CODE:
select distinct `Year` from `updated` order by `Year` asc;
/* Affected rows: 0 Найденные строки: 3 411 Длительность 1 query: 00:01:22 */
select distinct `Publisher` from `updated` order by `Publisher` asc;
/* Affected rows: 0 Найденные строки: 117 782 Длительность 1 query: 00:01:37 (+ 1,139 sec. network) */
select distinct `Language` from `updated` order by `Language` asc;
/* Affected rows: 0 Найденные строки: 2 202 Длительность 1 query: 47,845 sec. */
select distinct `Library` from `updated` order by `Library` asc;
/* Affected rows: 0 Найденные строки: 563 Длительность 1 query: 45,162 sec. */
select * from updated where ID = 2000000;
/* Affected rows: 0 Найденные строки: 1 Предупреждения: 0 Длительность 1 query: 0,749 sec. */
/* Affected rows: 0 Найденные строки: 3 411 Длительность 1 query: 00:01:22 */
select distinct `Publisher` from `updated` order by `Publisher` asc;
/* Affected rows: 0 Найденные строки: 117 782 Длительность 1 query: 00:01:37 (+ 1,139 sec. network) */
select distinct `Language` from `updated` order by `Language` asc;
/* Affected rows: 0 Найденные строки: 2 202 Длительность 1 query: 47,845 sec. */
select distinct `Library` from `updated` order by `Library` asc;
/* Affected rows: 0 Найденные строки: 563 Длительность 1 query: 45,162 sec. */
select * from updated where ID = 2000000;
/* Affected rows: 0 Найденные строки: 1 Предупреждения: 0 Длительность 1 query: 0,749 sec. */
Просто попробуйте выполнить похожие операции на файлах прямого доступа для сравнения затрат времени
28. Flat - 27 июля 2018 — 12:14 - перейти к сообщению
1Bot пишет:
Что сказать, сами придумываем велосипеды, которые уже давно ездят в существующих СУБД.
Спасибо за инфо, это многим будет интересно. Я знаком с реляционными базами данных, так как читал соответствующую литературу, также немного знаю язык sql запросов.
Тут надо понять, что универсальные решения зачастую становятся не эффективны, когда применяются в специфических приложениях с ограниченным функционалом, который можно описать своим компактным языком.
Существующие СУБД это универсальные решения, со своим большим языком описаний на все случаи жизни. Большие проекты требуют мощных баз. К сожалению, такая универсализация приводит к отрицательным результатам, особенно что касается политики безопасности. Чем мощнее язык, тем больше в нём дыр. Чем компактней язык, чем больше он заточен на цель, тем меньше в нём лазеек.
Теперь про эффективность.
Я в курсе про индексацию. Знаю по крайней мере две попытки создания файловой базы данных прямой выборки. Это база некоего youROCK https://habr.com/post/70140/
в которой он применил поиск по б-деревьям. Б-деревья довольно сложная штука. На пыхе их можно реализовать но код превратится в абсолютно нечитаемую галиматью. Я ознакомился с кодом. Он пользуется специальными индексными файлами, что усложняет движок. он писал, что перевёл свой форум с sql на свою базу и не заметил потерь в скорости.
Также существует подобная база cms Rumba. Там тоже индексные файлы. Я нашёл простое решение, которое позволяет отказаться от индексных файлов. Вот в чём дело. Это намного упрощает базу и работу с ней без потерь эффективности.
1Bot пишет:
1Bot , что-то не впечатляет. Всё в районе 1 сек крутится. Так дело не пойдёт! Бинарный поиск сработает в десятки раз быстрее, хотя в базе 2 гига, хоть в 10 гигов. Это же бинарный поиск, который никому никогда не переплюнуть, программеры, которые в курсах, меня поймут.Приведу для сравнения примеры выборок из таблицы СУБД mysql c 2 242 208 записями (общим размером 2 ГБ), где каждая запись состоит из 47 полей
1Bot пишет:
Просто попробуйте выполнить похожие операции на файлах прямого доступа для сравнения затрат времени
К сожалению, сейчас не смогу создать подобную базу и произвести сравнение,так как сначала нужны API для работы с моей базой, да и саму базу надо эмулировать. Потом, когда сделаю достаточно функций, проверим обязательно на огромных базах, чтобы ни у кого не осталось никаких сомнений в том, что наша доморощенная может не просто конкурировать на равных с мускульными, но и в некоторых моментах и превосходить их.
По делам текущим.
Вчера доработал функцию бинарного поиска и сделал обёрточную функцию. Так что дело идёт полным ходом, Следите за новостями)))
29. 1Bot - 27 июля 2018 — 12:35 - перейти к сообщению
Flat пишет:
Сейчас популярно обьясню))
Например имеем такую базу данных, в которой каждая строка это одна запись, а отдельные поля записи отделены каким-либо редко используемым знаком. Зачастую для этой цели используется знак |(вертикальная черта):
0000001| admin|password|ad@kuku.com|ad
0000002| masha|password|gg@zuzu.com|me
0000003|grisha|password|ff@bubu.com|me
и т.д
Естественно, что вертикальную черту в текстах необходимо заменить на html сущности.
Каждое поле имеет определённую длину, которая прописана в скрипте, а общая длина записи постоянна.
Чтобы получить отдельную запись или отдельное поле при прямом доступе, ненужно качать всю базу в память, а необходимо, просто напросто, подвести считывающую головку(виртуальную, ибо сейчас уже используют твёрдотельные накопители) непосредственно к записи и считать её в память. Делается это очень просто.
Например имеем такую базу данных, в которой каждая строка это одна запись, а отдельные поля записи отделены каким-либо редко используемым знаком. Зачастую для этой цели используется знак |(вертикальная черта):
0000001| admin|password|ad@kuku.com|ad
0000002| masha|password|gg@zuzu.com|me
0000003|grisha|password|ff@bubu.com|me
и т.д
Естественно, что вертикальную черту в текстах необходимо заменить на html сущности.
Каждое поле имеет определённую длину, которая прописана в скрипте, а общая длина записи постоянна.
Чтобы получить отдельную запись или отдельное поле при прямом доступе, ненужно качать всю базу в память, а необходимо, просто напросто, подвести считывающую головку(виртуальную, ибо сейчас уже используют твёрдотельные накопители) непосредственно к записи и считать её в память. Делается это очень просто.
Ключевой момент здесь Каждое поле имеет определённую длину, которая прописана в скрипте, а общая длина записи постоянна.
Для текстовых данных это едва ли возможно без чрезмерных затрат места.
Flat пишет:
Я нашёл простое решение, которое позволяет отказаться от индексных файлов. Вот в чём дело. Это намного упрощает базу и работу с ней без потерь эффективности.
...
Вчера доработал функцию бинарного поиска и сделал обёрточную функцию. Так что дело идёт полным ходом, Следите за новостями
...
Вчера доработал функцию бинарного поиска и сделал обёрточную функцию. Так что дело идёт полным ходом, Следите за новостями
Алгоритмы бинарного поиска используются и при использовании индексов СУБД (там используют Б-деревья для поиска). Сам алгоритм берет начало в 197х годах.
Если получится что-то эффективнее - то только на специфических данных.
30. Flat - 27 июля 2018 — 13:31 - перейти к сообщению
1Bot пишет:
Для текстовых данных это едва ли возможно без чрезмерных затрат места.
Я продумал и это.
Например каким образом добавлять в базу сообщения пользователя, которые имеют разную длину? Или в базе пользователей есть к примеру поле "о себе". Ведь они могут быть разной длины. Выделять жёстко заданное количество байт под поле? Не вариант, так как это ограничит длину текста, и к тому же, приведёт к потерям дискового пространства если длина текста небольшая.
Решение очень простое: создаём так называемые расширенные поля записей. Например имеем основную запись с сообщением пользователя:
123|01|igor|Привет, это текст моего сообщения
Первое число это id пользователя, затем идёт поле количества записей(об этом ниже) имя и сам текст. Если текст не влезает в отведённое ограниченное поле, то создаём дополнительную запись такого вида:
123|02|igor|Привет, это текст моего сообщения
123|c|,которое вы сейчас читаете.
Второе поле "с" означает, что расширяется поле сообщения. В первой записи цифра 02 теперь указывает на то, что запись состоит из двух записей под одним и тем же id.
Если остается неиспользуемое место, то оно заполняется пробелами.
Таким образом мы полностью уходим от проблемы потери места. Максимум потеряем несколько лишних десятков байтов. Также теперь возможны сообщения любой длины.