HTML5 IndexedDB,Web SQL数据库和浏览器大战
我开始开发具有脱机数据库存储要求的Web应用程序。 长话短说,应用程序应该可以运行在:
- Chrome首选桌面浏览器之一
- iOS上的Safari
- Android的原生浏览器(基于V8和WebKit)
所以问题是select哪种技术:IndexedDB或Web SQL数据库?
关于Web SQL数据库,一方面可以在任何一种情况下使用。 另一方面,Mozilla声称Firefox永远不会实现它,并且根据HTML5 工作草案的规范已经陷入了僵局:
这个规范已经陷入僵局:所有感兴趣的实现者都使用了相同的SQL后端(Sqlite),但是我们需要多个独立的实现来沿着标准化path前进。 在另一个实现者对实现这个规范感兴趣之前,SQL方言的描述只是对Sqlite的一个引用,这对于一个标准是不可接受的。 如果您是实现独立SQL后端的实现者,请联系编辑,以便他可以编写一个方言规范,从而使规范向前迈进。
IndexedDB是Mozilla推崇的另一种select,但它只会在Firefox 4中出现.Microsoft感兴趣,Chrome也会支持它。 我对于苹果公司关于IndexedDB的计划一无所知。
我个人倾向于selectWeb SQL数据库,但仅仅因为我习惯了SQLite,我喜欢SQL的强大function和performance力,而且我理解了关系模型。 IndexedDB对我来说是一个不确定的因素。
这就是说,我害怕在错误的马上投注。 即使IndexedDB成为标准,假设对Web SQL数据库的支持将继续存在是否安全?
(关于CouchDB的一个注释:你也可以把它看作是一种替代方法吗?)
考虑到只有WebSQL支持你列出的所有三个要求,你不应该select简单吗? 您对Safari或Android的发展路线图没有深入的了解,因此请使用您的可用function。
那么,就像所有的计算一样,游戏是“抽象”的。
如果你能想出一个适用于SQL存储和键/值存储的适当的层,那么理想情况下,你可以将问题隔离开来,并且可以在特定的浏览器上支持适当的实现。 如果你的数据模型和访问模式不适合最小公分母(即ak / v存储),那么这几乎可以解决你的问题。
如果您可以使用任何一家商店,那么在一个体面的访问层上工作,并从这个方向来解决问题。
注意,仅仅因为你在后端有一个k / v存储,并不意味着你必须将数据build模为只有ak / v模型。 基本上所有的数据库在后端是ak / v商店。 如果你没有疯狂的数据量,你可以做很多事情。 有了大量的数据,你可能不得不跳过这些数据,这可能会让你在性能上损失惨重,而使用较less的数据却可能看不到这些数据。 一切都依赖。
您的数据库是否需要远远超过关键/价值商店? 如果没有,我已经find了一些本地基于浏览器的数据库抽象的JavaScript包。 一个这样的包是jStore:
http://code.google.com/p/jquery-jstore/
我最近使用它来添加本地键/值存储。 它有很好的文档logging,集成时间可以忽略不计 – 它通过API支持一系列存储后端,包括闪存本地存储。
CouchDB是一个很好的解决scheme – 对于与您不太一致的问题。 看看couchone手机 。 不是严格的'networking应用程序',但它可以提供一个数据库基础,你可以运行,如果你有规范的一些灵活性。
根据你在iOS上对Safari的要求,除了WebSQL之外别无select。 Opera和Blackberry等手机浏览器支持WebSQL。 即使他们有IndexedDB,我也不认为他们会删除WebSQL支持。 不知何故,它们是互补的。
另一方面,在浏览器存储战争中,IndexedDB获胜。 IE和FF只会有IndexedDB。 具有讽刺意味的是,FF在Sqlite上实现了IndexedDB。
我想说的是IndexedDB不仅仅是关键的价值存储。 它有索引和交易。 这些只有两个几乎所有的SQL查询function,包括连接,条件和sorting。 起初由于它的asynchronousAPI而不明显。
IndexedDB的性能比WebSQL好。 这是更安全的。 对于javascript用例更为灵活。 最后它更容易使用。
为了说明这种情况,我将使用我的库中的 sudo代码,但是可以直接使用IndexedDB API:
“人”商店有索引字段“名称”和列表索引字段“爱好”。 在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
对象存储只有一个列出的索引字段friend_list
。 它使用人员对象存储键作为线外主键。 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
使用sorting合并algorithm来查找匹配键,但是这里显示的是天真的嵌套循环连接algorithm。 所以表join是可能的,但你必须编码连接algorithm。 但是像Zigzag合并这样的新algorithm比Sqlite更快,因为所有的input都是sorting的,游标可以很好的提前,更重要的是join过程可以利用不在数据库中的外部知识。 使用SQL,连接操作是不透明的。
除此之外,IndexedDB可以使用像stream式处理和映射/减less处理之类的技术。
我的build议是去IndexDB ,因为有一个IndexDB的Polyfill可用。
所有支持WebSQL的浏览器都可以这样支持IndexDB API 。 反过来,实现起来会非常困难,所以如果你想访问所有了解某些数据库API的浏览器,IndexDB是当今最好的select。
注意:即使这个问题还是旧的,它仍然是相关的,所以我认为这个问题的答案值得更新。 对于只有链接的解决scheme感到抱歉,所以我只添加了通常长期目的地的链接:W3C和GitHub
我在2016年回答了这个问题(在你问这个问题之后的5年),所有关于WebSQL弃用的问题依然存在 。 另一方面,IndexedDB 则得到了所有主stream浏览器厂商的支持 。
所以对于任何可能发现自己面临同样决定的人,都可以使用IndexedDB。
然而,正如其他人所暗示的那样,这样的决定并不一定是必须作出的。 人们可以简单地select(或制作)利用客户端机器上可用数据库的库。
BakedGoods与这里已经提到的这些库有几种不同之处; 最有针对性的是,它允许要使用的存储types被明确地指定,从而允许开发者将其他因素(例如性能特征)引入到决策过程中。
有了它,支持任何数据库types的存储操作是一个问题…
…为两种数据库types指定适当的操作选项和等效configuration:
//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){} });
其简单的界面和无与伦比的存储设备支持是以缺乏对某些存储设备特定configuration的支持为代价的。 例如,它不支持在具有多列主键的WebSQL表中存储操作的传导。
所以如果你大量使用这些types的function,你可能想看看其他地方。
哦,为了完全透明,BakedGoods是由你的真正维护:)。