Używaj SQLite do wydajnego obsługiwania wszystkich potrzeb związanych z przechowywaniem danych w internecie.
SQLite to popularny, otwarty, lekki, wbudowany system zarządzania relacyjną bazą danych. Wielu deweloperów używa go do przechowywania danych w uporządkowany i łatwy w użyciu sposób. Ze względu na niewielki rozmiar i niskie wymagania dotyczące pamięci SQLite jest często używany jako silnik bazy danych na urządzeniach mobilnych, w aplikacjach na komputery i w przeglądarkach internetowych.
Jedną z najważniejszych cech SQLite jest to, że jest to baza danych bezserwerowa, co oznacza, że do działania nie wymaga oddzielnego procesu serwera. Zamiast tego baza danych jest przechowywana w jednym pliku na urządzeniu użytkownika, co ułatwia integrację z aplikacjami.
SQLite oparte na Web Assembly
Istnieje kilka nieoficjalnych wersji SQLite opartych na Web Assembly (Wasm), które umożliwiają korzystanie z niej w przeglądarkach internetowych, np. sql.js. Podprojekt sqlite3 WASM/JS to pierwsze przedsięwzięcie oficjalnie powiązane z projektem SQLite, dzięki któremu kompilacje biblioteki w Wasmie stały się stałymi elementami rodziny obsługiwanych produktów SQLite. Konkretne cele tego projektu to:
- Powiązanie interfejsu API sqlite3 niskiego poziomu, który jest jak najbardziej zbliżony do interfejsu C pod względem użycia.
- Obiektowy interfejs API wyższego poziomu, bardziej zbliżony do sql.js i implementacji w stylu Node.js, który komunikuje się bezpośrednio z interfejsem API niższego poziomu. Tego interfejsu API należy używać w tym samym wątku co interfejs API niskiego poziomu.
- Interfejs API oparty na Workerze, który komunikuje się z poprzednimi interfejsami API za pomocą wiadomości Worker. Ten interfejs jest przeznaczony do używania w głównym wątku, a interfejsy API niższego poziomu są instalowane w wątku roboczym i komunikują się z nim za pomocą wiadomości roboczych.
- Wariant interfejsu Worker API oparty na obietnicach, który całkowicie ukrywa przed użytkownikiem aspekty komunikacji między wątkami.
- Obsługa trwałego przechowywania po stronie klienta za pomocą dostępnych interfejsów API JavaScript, w tym Origin Private File System (OPFS).
Używanie SQLite Wasm z backendem trwałości Origin Private File System
Instalowanie biblioteki z npm
Zainstaluj pakiet @sqlite.org/sqlite-wasm z npm za pomocą tego polecenia:
npm install @sqlite.org/sqlite-wasm
Origin Private File System
Prywatny system plików pochodzenia (OPFS, część interfejsu File System Access API) został rozszerzony o specjalną powierzchnię, która zapewnia bardzo wydajny dostęp do danych. Ta nowa powierzchnia różni się od dotychczasowych tym, że oferuje bezpośredni i wyłączny dostęp do zapisu treści pliku. Ta zmiana, wraz z możliwością ciągłego odczytywania niezapisanych zmian i dostępnością wariantu synchronicznego w przypadku dedykowanych procesów roboczych, znacznie zwiększa wydajność i umożliwia nowe zastosowania.
Jak możesz sobie wyobrazić, ostatni punkt celów projektu, czyli obsługa trwałego przechowywania danych po stronie klienta za pomocą dostępnych interfejsów API JavaScript, wiąże się z rygorystycznymi wymaganiami dotyczącymi wydajności w zakresie zapisywania danych w pliku bazy danych.
Właśnie tu do akcji wkracza Origin Private File System, a konkretnie metoda createSyncAccessHandle()
obiektów FileSystemFileHandle
. Ta metoda zwraca obiekt Promise, który jest rozpoznawany jako obiekt FileSystemSyncAccessHandle
, którego można używać do synchronicznego odczytywania i zapisywania pliku. Synchroniczny charakter tej metody zapewnia korzyści w zakresie wydajności, ale dlatego można jej używać tylko w dedykowanych Web Workerach w przypadku plików w systemie plików prywatnych pochodzenia, aby nie blokować głównego wątku.
Ustawianie wymaganych nagłówków
Pobrane archiwum SQLite Wasm zawiera m.in. pliki sqlite3.js
i sqlite3.wasm
, które składają się na kompilację sqlite3 WASM/JS. Katalog jswasm
zawiera podstawowe pliki sqlite3, a katalog najwyższego poziomu – aplikacje demonstracyjne i testowe. Przeglądarki nie będą wyświetlać plików Wasm z adresów URL file://
, więc wszystkie aplikacje utworzone w ten sposób wymagają serwera WWW, który podczas wyświetlania plików musi zawierać w odpowiedzi te nagłówki:
Cross-Origin-Opener-Policy
ustawiona na dyrektywęsame-origin
, która izoluje kontekst przeglądania wyłącznie w przypadku dokumentów z tej samej domeny. Dokumenty z innych domen nie są wczytywane w tym samym kontekście przeglądania.Cross-Origin-Embedder-Policy
ustawiony narequire-corp
dyrektywę, dzięki czemu dokument może ładować zasoby tylko z tego samego źródła lub zasoby wyraźnie oznaczone jako możliwe do załadowania z innego źródła.
Powodem stosowania tych nagłówków jest to, że SQLite Wasm zależy od
SharedArrayBuffer
,
a ustawienie tych nagłówków jest częścią jego wymagań dotyczących bezpieczeństwa.
Jeśli sprawdzisz ruch za pomocą Narzędzi deweloperskich, powinny się w nim znaleźć te informacje:
Test szybkości
Zespół SQLite przeprowadził testy porównawcze swojej implementacji WebAssembly z wycofaną usługą Web SQL. Te testy porównawcze pokazują, że SQLite Wasm jest zwykle mniej więcej tak samo szybki jak Web SQL. Czasami jest trochę wolniejsza, czasami trochę szybsza. Wszystkie szczegóły znajdziesz na stronie wyników.
Przykładowy kod na początek
Jak wspomnieliśmy wcześniej, SQLite Wasm z backendem Origin Private File System musi działać w kontekście Worker. Dobra wiadomość jest taka, że biblioteka automatycznie zajmuje się tym wszystkim, a Ty możesz jej używać bezpośrednio w głównym wątku.
import { sqlite3Worker1Promiser } from '@sqlite.org/sqlite-wasm';
(async () => {
try {
console.log('Loading and initializing SQLite3 module...');
const promiser = await new Promise((resolve) => {
const _promiser = sqlite3Worker1Promiser({
onready: () => {
resolve(_promiser);
},
});
});
console.log('Done initializing. Running demo...');
let response;
response = await promiser('config-get', {});
console.log('Running SQLite3 version', response.result.version.libVersion);
response = await promiser('open', {
filename: 'file:worker-promiser.sqlite3?vfs=opfs',
});
const { dbId } = response;
console.log(
'OPFS is available, created persisted database at',
response.result.filename.replace(/^file:(.*?)\?vfs=opfs$/, '$1'),
);
await promiser('exec', { dbId, sql: 'CREATE TABLE IF NOT EXISTS t(a,b)' });
console.log('Creating a table...');
console.log('Insert some data using exec()...');
for (let i = 20; i <= 25; ++i) {
await promiser('exec', {
dbId,
sql: 'INSERT INTO t(a,b) VALUES (?,?)',
bind: [i, i * 2],
});
}
console.log('Query data with exec()');
await promiser('exec', {
dbId,
sql: 'SELECT a FROM t ORDER BY a LIMIT 3',
callback: (result) => {
if (!result.row) {
return;
}
console.log(result.row);
},
});
await promiser('close', { dbId });
} catch (err) {
if (!(err instanceof Error)) {
err = new Error(err.result.message);
}
console.error(err.name, err.message);
}
})();
Prezentacja
Zobacz powyższy kod w działaniu w wersji demonstracyjnej. Koniecznie zapoznaj się z kodem źródłowym na GitHubie. Zwróć uwagę, że wersja osadzona poniżej nie korzysta z backendu OPFS, ale gdy otworzysz wersję demonstracyjną w osobnej karcie, będzie ona z niego korzystać.
Debugowanie Origin Private File System
Aby debugować dane wyjściowe systemu plików OPFS w SQLite Wasm, użyj rozszerzenia do Chrome OPFS Explorer.
Po zainstalowaniu rozszerzenia otwórz Narzędzia deweloperskie w Chrome, wybierz kartę OPFS Explorer i możesz sprawdzić, co SQLite Wasm zapisuje w systemie plików prywatnych pochodzenia.
Jeśli w oknie Eksploratora OPFS w Narzędziach deweloperskich wybierzesz dowolny plik, możesz go zapisać na dysku lokalnym. Następnie możesz użyć aplikacji takiej jak SQLite Viewer, aby sprawdzić bazę danych i upewnić się, że SQLite Wasm działa zgodnie z założeniami.
Uzyskiwanie pomocy i przesyłanie opinii
SQLite Wasm jest rozwijana i utrzymywana przez społeczność SQLite. Uzyskaj pomoc i prześlij opinię, wyszukując informacje i publikując posty na forum pomocy. Pełna dokumentacja jest dostępna w witrynie SQLite.