HTML5 IndexEdDB、Web SQLデータベース、ブラウザ戦争
質問
オフラインのデータベースストレージ要件を備えたWebアプリの開発を開始しています。簡単に言えば、アプリは次のように実行できるはずです
- 主要なデスクトップブラウザーの1つであるChromeが望ましい
- iOSのサファリ
- Androidのネイティブブラウザ(V8とWebKitに基づく)
質問は、どのテクノロジーを選択するかです:indexedDBまたはWeb SQLデータベース?
Web SQLデータベースに関しては、一方では、上記のシナリオのいずれかで使用する準備ができています。一方、MozillaはFirefoxが決してそれを実装しないと述べ、HTML5に順調に進むと述べています ワーキングドラフト 仕様は行き詰まりに達しました。
この仕様は行き詰まりに達しました。すべての関心のある実装者は同じSQLバックエンド(SQLite)を使用していますが、標準化パスに沿って進むには複数の独立した実装が必要です。別の実装者がこの仕様の実装に関心があるまで、SQL方言の説明は、標準には受け入れられないSQLiteへの参照として単に残されています。独立したSQLバックエンドの実装に関心のある実装者である場合は、エディターに連絡して、方言の仕様を作成できるようにして、この仕様を前進させることができます。
IndexEdDBはMozillaが提唱する代替案ですが、Firefox 4にのみ掲載されます。Microsoftは興味があり、Chromeもサポートします。 IndexedDBに関するAppleの計画については何も知りません。
私は個人的にWeb SQLデータベースを選択する傾向がありますが、SQLiteに慣れているからといって、SQLのパワーと表現力が好きで、リレーショナルモデルを理解しています。私にとってindexedDBは不確実性です。
とはいえ、私は間違った馬に賭けることを恐れています。 indexedDBが標準になったとしても、Web SQLデータベースのサポートが存在し続けると想定するのは安全ですか?
(CouchDBに関するメモ:あなたもそれを代替として見ていますか?)
解決
WebQLのみがリストした3つの要件すべてをサポートすることを考慮すると、選択した選択は簡単ではありませんか? SafariまたはAndroidの開発ロードマップについての洞察がないため、利用可能なものを使用してください。
他のヒント
まあ、すべてのものと同様に、ゲームは「抽象化」です。
SQLストアとキー/バリューストアの両方で機能する適切なレイヤーを思いつくことができる場合、理想的には問題から分離され、特定のブラウザでの適切な実装をサポートできます。データモデルとアクセスパターンが最も低い一般的な分母(つまりAK/Vストア)に適合しない場合、それはほとんどそこで問題を解決します。
どちらかを使用できる場合は、適切なアクセスレイヤーで作業し、その方向から問題にアプローチします。
心に留めてください。バックエンドにAK/Vストアがあるからといって、AK/Vモデルのみとしてデータをモデル化する必要があるわけではありません。基本的に、すべてのDBがバックエンドにあるAK/Vストアです。非常に量のデータがない場合は、多くのことをすることができます。大量のデータを使用すると、ジャンプする必要があるフープは、少量のデータでは見られない場合があるパフォーマンスにかかる場合があります。すべて依存します。
データベースはキー/バリューストアを大幅に超えて必要ですか?そうでない場合は、ローカルブラウザーベースのデータベース抽象化用のJavaScriptパッケージを多数見つけました。そのようなパッケージの1つはjstoreです:
http://code.google.com/p/jquery-jstore/
最近、ローカルキー/値ストレージを追加するために使用しました。十分に文書化されており、統合時間はごくわずかでした。APIを介して、フラッシュローカルストレージを含むストレージバックエンドの配列をサポートしています。
CouchDBは優れたソリューションです。これは、あなたとはまったく一致していない問題のためです。チェックアウト Couchone Mobile. 。厳密に「Webアプリ」ではありませんが、仕様に柔軟性がある場合は、実行できるデータベースファンデーションを提供する場合があります。
私の推薦は次のとおりです indexdbに移動します, 、あるからです indexDBポリフィル 利用可能。
WebQLをサポートするすべてのブラウザは、をサポートできます indexDB API こちらです。その逆の方法は実装が非常に困難です。したがって、DB APIを知っているすべてのブラウザに到達したい場合、IndexDBは今日の最良の選択です。
注:この質問が古いことでさえ、まだ関連しているので、この質問に対する答えは更新に値すると思います。リンクのみのソリューションで申し訳ありませんので、通常は長続きする目的地へのリンクのみを追加しました:W3CとGitHub
iOSでのSafariの指定された要件により、WebQL以外の選択肢はありません。 WebQLは、OperaやBlackBerryなどの他のモバイルブラウザでサポートされています。 IndexEdDBを持っていても、WebQLサポートを削除するとは思わない。どういうわけか彼らは補完的です。
一方、ブラウザストレージ戦争では、IndexEdDBが永久に勝ちます。 IEとFFにはindexedDBのみがあります。皮肉な事実は、FFがsqliteの上にindexeddbを実装することです。
私が言いたいのは、indexedDBは単なるキーバリューストア以上のものです。インデックスとトランザクションがあります。これらは、Join、Conditional、Sortingを含むSQLクエリのほぼすべての機能を作成します。その非同期APIのため、最初は明らかではありません。
IndexEdDBのパフォーマンスは、WebQLよりも優れています。より安全です。 JavaScriptの使用ケースにより柔軟性があります。最後に、より簡単に使用できます。
ケースを説明するために、からのsudoコードを使用します 私の図書館, 、しかし、indexedDB APIを直接使用できます。
「People」ストアには、インデックスフィールド名「名前」があり、インデックス付きフィールド「趣味」がリストされています。 JSONで、
people = {
name: 'Foo Bar',
email: 'foo@bar.com'
hobby: ['camping', 'swimming']};
趣味が「キャンプ」である「人」から名前を取得する。
var req = db.keys('people', 'hobby', IDBKeyRange.only('camping'));
req.done(function(campers) {
db.keys('people', campers, 'name').done(function(names) {
console.log(names);
});
});
このコードについて興味深いのは、シリアル化が含まれていないことです。したがって、それは非常に速いです。
次の例は、友情グラフのクエリを示しています。 friendship
オブジェクトストアには、リストされたインデックスフィールドが1つしかありません friend_list
. 。これは、Out-Ofl-LineプライマリキーとしてPeople Object Storeキーを使用します。 people
オブジェクトストアには多くの属性があります location
分野。クエリは、知っている友人のリストを見つけることです me
と other_guy
そして「シンガポール」にあります。
var q1 = new ydn.db.Iterator('friendship', 'friend_list', IDBKeyRange.only(me));
var q2 = new dn.db.Iterator('friendship', 'friend_list', IDBKeyRange.only(other_guy));
// if location is not indexed, a filtered value query is used.
var q3 = new ydn.db.Iterator('people', new ydn.db.Expression(['"location"', "'Singapore'", '=']));
// if location is indexed, an index query is used.
// var q3 = new ydn.db.Iterator('people', 'location', IDBKeyRange.only('Singapore'));
var current_loop = 2; // start from inner loop
var join_algo = function(keys, index_keys) {
var advancement = [];
advancement[keys.length - 1] = null;
var has_adv = false;
for (var i = 0; i < keys.length; i++) {
if (!goog.isDef(keys[i])) {
// completed iterator
if (i != 0) {
advancement[i] = false; // request to restart the iteration
advancement[i - 1] = true; // advance outer iterator
current_loop = i - 1;
} // i == 0 means we are done.
has_adv = true;
break;
}
}
if (!has_adv) {
// continue looping current
advancement[current_loop] = true;
}
return advancement;
}
var result = db.scan([q3, q1, q2], join_algo);
result.done(function(keys, index_keys, values) {
console.log(values); // should get desire list of friends
});
繰り返しますが、この結合クエリは単なるキースキャンであるため、非常に高速です。デフォルトで scan
並べ替えられたマージアルゴリズムを使用して一致するキーを見つけますが、ここではナイーブネストループ結合アルゴリズムを表示します。したがって、テーブル結合は可能ですが、アルゴリズムを結合する必要があります。しかし、Zigzagマージのような新しいアルゴリズムは、すべての入力がソートされているため、SQLiteで可能なよりも高速です。カーソルは十分に進んでおり、さらに重要なことに、プロセスに参加すると、データベースにない外部の知識を活用できます。 SQLを使用すると、接合操作は不透明です。
それ以外のindexedDBは、ストリーミングやマップ/削減などの手法を使用できます。
私は2016年(この質問をしてから5年後)にこれに返信しています。 WebQLの非難はまだ立っています. 。一方、indexeddb、 主要なブラウザベンダーのすべてのサポートを楽しんでいます.
したがって、ここに自分自身が同じ決定に直面している人には、indexedDBを使用してください。
しかし、ここで他の人が暗示しているように、そのような決定は必ずしも行わなければならない決定ではありません。クライアントマシンで利用可能なデータベースを使用するライブラリを単に選択(または作成する)ことができます。
BakedGoods ここでいくつかの方法で提案されているこのようなライブラリとは異なります。最も適切には、明示的に指定されるように使用できるストレージタイプを可能にし、開発者が意思決定プロセスに他の要因(パフォーマンス特性など)を導入できるようにします。
それに伴い、データベースタイプのいずれかでストレージ操作を実施することは、の問題です...
...両方のデータベースタイプの適切な操作オプションと同等の構成を指定します。
//If the operation is a set(), and the referenced structures
//don't exist, they will be created automatically.
var webSQLOptionsObj = {
databaseName: "Example_DB",
databaseDisplayName: "Example DB",
databaseVersion: "",
estimatedDatabaseSize: 1024 * 1024,
tableData: {
name: "Main",
keyColumnName: "lastName",
columnDefinitions: "(lastName TEXT PRIMARY KEY, firstName TEXT)"
},
tableIndexDataArray: [name: "First_Name_Index", columnNames: "(firstName)"]
};
var indexedDBOptionsObj = {
databaseName: "Example_DB",
databaseVersion: 1,
objectStoreData: {
name: "Main",
keyPath: lastName,
autoIncrement: false
},
objectStoreIndexDataArray: [
{name: "First_Name_Index", keyPath: "firstName", unique: false, multiEntry: false}
],
};
var optionsObj = {
conductDisjointly: false,
webSQL: webSQLOptionsObj,
indexedDB: indexedDBOptionsObj
};
...そして操作の実施:
bakedGoods.set({
data: [
{value: {lastName: "Obama", firstName: "Barack"}},
{value: {lastName: "Biden", firstName: "Joe"}}
],
storageTypes: ["indexedDB", "webSQL"],
options: optionsObj,
complete: function(byStorageTypeStoredItemRangeDataObj, byStorageTypeErrorObj){}
});
そのシンプルなインターフェースと比類のないストレージ施設のサポートは、一部のストレージ施設固有の構成のサポートが不足しているために販売されています。たとえば、マルチカラムのプライマリキーを備えたWebQLテーブルのストレージ操作の伝導をサポートしていません。
したがって、これらのタイプの機能を大量に使用する場合は、他の場所を見たいと思うかもしれません。
ああ、そして完全な透明性のために、BakedGoodsは本当にあなたによって維持されています:)。