Размещение баз данных SQLite на страницах GitHub (или любом другом хостере статических файлов)

(или любой поставщик статических файлов)

я писал “href =” https://phiresky.github.io/youtube-sponsorship-stats/?uploader=Adam+Ragusea “> крошечный веб-сайт для отображения статистики о том, сколько спонсируемый контент создатель Youtube со временем, когда я заметил, что часто пишу небольшой инструмент в виде веб-сайта, который запрашивает некоторые данные из базы данных, а затем отображает их в виде графика, таблицы или чего-то подобного. Но если вы хотите использовать базу данных , вам либо нужно написать бэкэнд (который вам затем нужно будет размещать и поддерживать вечно), либо загрузить весь набор данных в браузер (что не так хорошо, когда набор данных больше, чем 17 МБ).

Раньше, когда я использовал внутренний сервер для этих небольших побочных проектов, в какой-то момент какой-то внешний API выходил из строя или срок действия ключа истекает, или я забываю о бэкэнде и перестаю платить за любой VPS, на котором он был. Затем, когда я возвращаюсь к нему спустя годы, меня раздражает, что он исчез, и я проклинаю себя за то, что полагаюсь на внешний сервис – или на себя. в течение более длительного периода времени.

Хостинг статического веб-сайта намного проще, чем «настоящего» сервер – есть много бесплатных и надежных опций (например, GitHub, GitLab Pages, Netlify и т. д.), и он масштабируется практически до бесконечности без каких-либо усилий.

Итак, я написал инструмент, позволяющий использовать настоящую базу данных SQL на статически размещенном веб-сайте!

Вот демонстрация с использованием”href =” https://github.com/phiresky/world-development-indicators-sqlite/ “> Набор данных World Development Indicators – набор данных с 6 таблицами и более 8 миллион строк (1000 Всего Мбайт).

Демо

    выберите   country_code  ,   long_name   из   wdi_country   предел     3  ;    

Как видите, мы можем запросить”> таблица wdi_country при извлечении только 1 КБ данных!

Это полноценный механизм запросов SQLite . Таким образом, мы можем использовать, например, “href =” https://www.sqlite.org/json1.html “> Функции SQLite JSON :

Демо

 Выбрать  json_extract   (  arr  .значение ,     '$. foo.bar'  )     как   бар     из  json_each   (  '[{"foo": {"bar": 123}}, {"foo": {"bar": "baz"}}]'  )   в виде arr    

Мы также можем зарегистрировать JS-функции, чтобы их можно было вызывать из в запросе. Вот пример с “> getFlag функция, которая получает эмодзи флага страны:

    функция     getFlag  (код страны )     {        // просто магия юникода        возвращаться Нить.   fromCodePoint   (  ... Множество.из  (код страны ||   ""  )        .  карта(  c   =>     127397     +   c  .   codePointAt   ( )  )  )  ;        }            ожидание   db  .   create_function   (  "get_flag"  ,   getFlag  )       возвращаться Ждите db  . запрос(  `   Выбрать long_name, get_flag ("2-alpha_code") как флаг из wdi_country  , где регион не равен нулю и currency_unit = "Евро";       ` )    

“> Нажмите кнопку” Выполнить “, чтобы запустить следующие демонстрации. Вы можете изменить код по своему усмотрению, хотя, если вы сделаете запрос слишком широким, он будет получать большие объемы данных;)

Обратите внимание, что этот веб-сайт 123% размещается на хосте статических файлов (страницы GitHub).

Итак, как использовать базу данных в хостере статических файлов? Во-первых, SQLite (написанный на C) компилируется в WebAssembly. SQLite можно скомпилировать с”href =” https://emscripten.org/ “> emscripten без каких-либо изменений, аБиблиотека “href =” https://github.com/sql-js/sql.js/ “> sql.js представляет собой тонкую JS-оболочку вокруг кода wasm.

sql.js позволяет создавать и читать только базы данных, которые полностью находятся в памяти, поэтому я реализовал виртуальную файловую систему, которая извлекает фрагменты базы данных с запросами диапазона HTTP, когда SQLite пытается читать из файловой системы:”href =” https://github.com/phiresky/sql.js-httpvfs “> sql.js-httpvfs . С точки зрения SQLite, похоже, что он живой на обычном компьютере с пустой файловой системой, за исключением файла с именем”> /wdi.sqlite3 , из которого он может читать. Конечно, он не может писать в этот файл, но база данных только для чтения все еще очень полезно.

Поскольку получение данных через HTTP связано с довольно большими накладными расходами, нам нужно получать данные по частям и находить некоторый баланс между количеством запросов и используемой пропускной способностью. К счастью, SQLite уже организует свою базу данных в «страницах» с определенным пользователем “href =” https://www.sqlite.org/pgszchng2021. html “> размер страницы (по умолчанию 4 КиБ). установите для этой базы данных размер страницы 1 КиБ.

Вот пример простого поискового запроса по индексу:

Демо

 Выбрать indicator_code  ,   long_definition   из   wdi_series   где   имя_индикатора     знак равно    'Уровень грамотности, общее количество молодежи (% населения возраст 17 - 24) '   

Выполните указанный выше запрос и посмотрите журнал чтения страницы. SQLite выполняет 7 операций чтения для этого запроса.

      Три чтения страницы – это всего лишь некоторые, чтобы получить некоторую информацию о схеме (они уже кэшированы)

    • Две страницы чтения – это поиск по индексу в индексе”> в wdi_series (имя_индикатора)
      • Две страницы прочитаны на”> wdi_series данные таблицы (первая для поиска значения строки по первичному ключу, вторая для получения текстовых данных из “href =” https://www.sqlite.org/fileformat2.html#ovflpgs “> страница переполнения )

      • И индекс, и таблица считываются с помощью поиска в B-дереве.

        Более сложный запрос: в каких странах самый низкий уровень грамотности среди молодежи, основанный на последних данных после ?

        Демо

            с   newest_datapoints в виде   (        выберите   country_code  ,   indicator_code  ,   Макс  (год )   в виде год    из   wdi_data       присоединиться   wdi_series с использованием   (  indicator_code  )       где     имя_индикатора   =     'Уровень грамотности, общее количество молодежи (% возрастов людей 20 - 70 ) '      а также год  >     2010       группа от код страны     )       Выбрать c  .   краткое_имя   как  страна,   printf   (  '%. 1f% % ' ,   значение )   в виде    «Уровень грамотности молодежи»       из wdi_data     присоединиться  wdi_country c   с использованием (код страны )       присоединиться  newest_datapoints   используя     (  indicator_code , код страны ,   год )         заказывать от значение   asc     предел     17    

        Приведенный выше запрос должен выполнять – 24 Запросы GET с получением всего – 670 KiB, в зависимости от того, запускали ли вы также вышеперечисленные демоверсии. Обратите внимание, что для этого достаточно запросы, а не 670 (как и следовало ожидать при загрузке KiB с 1 KiB за раз). Это потому, что я реализовал систему предварительной выборки, которая пытается обнаруживать шаблоны доступа через три отдельные виртуальные считывающие головки и экспоненциально увеличивает размер запроса для последовательных чтений. Это означает, что сканирование индекса или таблицы, считывающее более нескольких килобайт данных, вызовет только количество запросов, которое является логарифмическим по отношению к общей длине сканирования в байтах. Эффект от этого можно увидеть, посмотрев на столбец «Шаблон доступа» в журнале чтения страницы. выше.

        Все это хорошо работает только тогда, когда у нас есть индексы в базе данных, которые хорошо соответствуют запросам. Например, индекс, используемый в приведенном выше запросе, является”> ИНДЕКС ВКЛ wdi_data (код_индикатора, код страны, год, значение) . Если этот индекс не включал столбец значения, механизм SQLite должен был бы выполнить еще одно произвольное (непредсказуемое) чтение и, таким образом, HTTP-запрос, чтобы получить фактическое значение для каждой точки данных. Если индекс был упорядочен”> country_code, indicator_code, … , тогда мы сможем быстро получить все показатели для одной страны, но не все значения страны один индикатор.

        Мы также можем использовать SQLite “href =” https://sqlite.org/fts5.html “> FTS , чтобы мы могли выполнять полнотекстовый поиск по более текстовой информации в база данных – в этом случае существует более индикаторы человеческого развития в базе данных с более подробным описанием.

        Демо

          Выбрать     из  indicator_search       где   indicator_search матч   'education femal *'        заказывать  по   рангу   предел     17    

        Общий объем данных в”> indicator_search Размер таблицы FTS составляет около 8 МБ. Приведенный выше запрос должен получать только около 100 KiB. Вы можете увидеть, как это устроено “href =” https://github.com/phiresky/world-development-indicators-sqlite/blob/gh-pages/postproc.sh#L20 “> здесь .

        И, наконец, вот более полная демонстрация полезности этой системы – вот интерактивный график показывает развитие нескольких стран с течением времени, для любых стран, которые вы хотите использовать любой индикатор из набора данных:

        Страны:

        Показатель:

        Физические лица, пользующиеся Интернетом (% населения)

        Дополнительная информация об этом индикаторе

        Код индикатора
        IT.NET.USER.ZS
        Длинное определение
        Пользователи Интернета – это люди, которые пользовались Интернетом (из любого места) в течение последних 3 месяцев. Интернетом можно пользоваться через компьютер, мобильный телефон, персонального цифрового помощника, игровой автомат, цифровое телевидение и т. Д.

        Статистическая концепция и методология

        Интернет – это всемирная общественная компьютерная сеть. Он обеспечивает доступ к ряду коммуникационных сервисов, включая World Wide Web, и переносит электронную почту, новости, развлекательные файлы и файлы данных, независимо от используемого устройства (не предполагается, что только через компьютер – это также может быть мобильный телефон, КПК, игровой автомат, цифровое телевидение и т. д.). Доступ может быть через фиксированную или мобильную сеть. Дополнительную / самую свежую информацию об источниках и примечаниях по странам также можно найти по адресу: https://www.itu.int/en/ITU-D/Statistics/Pages/stat/default.aspx

        Актуальность для развития
        Цифровая и информационная революция изменила способ обучения, общения, ведения бизнеса и лечения болезней в мире. Новые информационные и коммуникационные технологии (ИКТ) открывают широкие возможности для прогресса во всех сферах жизни во всех странах – возможности для экономического роста, улучшения здоровья, предоставления более качественных услуг, обучения через дистанционное образование, а также социальных и культурных достижений. Сегодняшние смартфоны и планшеты имеют мощность компьютера, эквивалентную мощности компьютеров вчерашнего дня, и предоставляют аналогичный набор функций. Таким образом, конвергенция устройств делает традиционное определение устаревшим. Сопоставимые статистические данные о доступе, использовании, качестве и доступности ИКТ необходимы для разработки политики, способствующей росту, а также для мониторинга и оценки воздействия сектора на развитие. Хотя основные данные о доступе доступны для многих стран, в большинстве развивающихся стран мало что известно о том, кто использует ИКТ; для чего они используются (школа, работа, бизнес, исследования, правительство); и как они влияют на людей и бизнес. Глобальное Партнерство по измерению ИКТ в целях развития помогает устанавливать стандарты, согласовывать статистику информационно-коммуникационных технологий и наращивать статистический потенциал в развивающихся странах. Однако, несмотря на значительные улучшения в развивающемся мире, разрыв между имущими и неимущими ИКТ сохраняется.

        Обратите внимание, что многие индикаторы доступны только для некоторых стран, например индикатор «Женщины, которые считают, что муж избивая жену, когда она сжигает пищу » основан на опросах, проводимых только в слаборазвитых странах.

        “id =” Bonus-dom-as-a-database “> Бонус: DOM как база данных

        Поскольку мы уже запускаем базу данных в нашем браузере, почему бы не использовать наш браузер в качестве базы данных, используя виртуальную таблицу называется “> dom ?

        Демо

          Выбрать считать (   )   в виде number_of_demos   из   дом       где   селектор матч   '. content div.sqlite-httpvfs-demo'  ;      Выбрать  считать  (   )   в виде  sqlite_mentions   из   дом       где   селектор матч   '. content p'  а также  textContent  нравиться   '% SQLite%'  ;    

        Мы даже можем вставлять элементы прямо в DOM:

        Демо

         вставлять  в дом   (  родитель  ,  название тэга,   textContent  )        Выбрать   'ul # outtable1'  ,     'ли'  ,  короткое имя      из   wdi_country   где   currency_unit  знак равно    «Евро»    

        Вывод:

        И обновить элементы в DOM:

        Демо

        Обновить  дом  набор textContent   =       get_flag   (  «2-альфа_код»  )     ||     ''     ||   textContent       из   wdi_country     где селектор   совпадение     'ul # outtable1> li '      а также текст  Содержимое   =   wdi_country  . короткое имя  


        Конечно, здесь все с открытым кодом. Основная реализация оболочки sqlite находится в"href =" https://github.com/phiresky/sql.js-httpvfs "> sql.js-httpvfs . Исходный код этого сообщения в блоге"href =" https://github.com/phiresky/blog/blob/master/posts/ / hosting-sqlite-databases-on-github-pages.md "> файл разметки pandoc , а демо-версии"href =" https://github.com/phiresky/blog/tree/master/client/sqlite-httpvfs "> custom " изолированный блок кода " Компонент React .

Leave a comment

Your email address will not be published. Required fields are marked *