English 中文(简体)
HTML5 IndexedDB、Web SQL数据库和浏览器大战
原标题:HTML5 IndexedDB, Web SQL Database and browser wars

我正在着手开发一款具有离线数据库存储需求的web应用程序。长话短说,该应用程序应该能够运行在:

  • One of the major desktop browsers, Chrome preferred
  • Safari on iOS
  • Android s native browser (based on V8 and WebKit)

所以问题是选择哪种技术:IndexedDB还是Web SQL数据库?

关于Web SQL数据库,一方面,它可以用于上述任何场景。另一方面,Mozilla表示Firefox永远不会实现它,并遵循HTML5工作草案规范陷入僵局:

这个规范已经陷入僵局:所有感兴趣的实现者都使用了相同的SQL后端(Sqlite),但我们需要多个独立的实现来沿着标准化的道路前进。在另一个实现者对实现这个规范感兴趣之前,SQL方言的描述只是对Sqlite的引用,这对于标准来说是不可接受的。如果您是一个对实现独立SQL后端感兴趣的实现者,请与编辑器联系,以便他可以为方言编写规范,从而允许该规范向前发展。

IndexedDB是Mozilla倡导的替代方案,但它只会出现在Firefox 4中。微软很感兴趣,Chrome也会支持它。我对苹果关于IndexedDB的计划一无所知。

我个人倾向于选择Web SQL数据库,但正是因为我习惯了SQLite,我喜欢SQL的强大功能和表达能力,并且我理解关系模型。对我来说,IndexedDB是一种不确定性。

也就是说,我害怕赌错马。即使IndexedDB成为标准,也可以认为对Web SQL数据库的支持将继续存在吗?

(CouchDB上的一条注释:你是否也将其视为一种替代方案?)

最佳回答

考虑到只有WebSQL支持您列出的所有三个需求,您的选择不应该很简单吗?您不了解Safari或Android的开发路线图,所以请使用您现有的内容。

问题回答

好吧,就像所有的计算一样,游戏是“抽象”的。

如果您能够在SQL存储和键/值存储上找到一个合适的层,那么,理想情况下,您可以与问题隔离,并可以在特定浏览器上支持适当的实现。如果您的数据模型和访问模式不符合最低公分母(即k/v存储),那么这基本上解决了您的问题。

如果你可以使用任何一个商店,那么就创建一个像样的访问层,并从这个方向解决问题。

请注意,仅仅因为您在后端有一个k/v存储并不意味着您必须将数据建模为仅一个k/v模型。从本质上讲,后台的所有数据库都是一个k/v存储。如果你没有大量的数据,你可以做很多事情。对于大量数据,您可能不得不跳过的障碍可能会使您的性能下降,而对于少量数据,您很可能看不到这一点。一切取决于情况。

我将在2016年(在您提出此问题5年后)对此进行回复,并回答与对WebSQL的弃用仍然存在.另一方面,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){}
});

其简单的界面和无与伦比的存储设施支持是以缺乏对某些存储设施特定配置的支持为代价的。例如,它不支持在具有多列主键的WebSQL表中执行存储操作。

因此,如果你大量使用这些类型的功能,你可能想另谋高就。

哦,为了完全透明,BakedGoods由您的公司真正维护:)。

我的建议是使用IndexDB,因为有IndexDB Polyfill可用。

所有支持WebSQL的浏览器都可以支持IndexDB API采用这种方式。反之则很难实现,因此,如果您想访问所有了解某些DB API的浏览器,IndexDB是目前的最佳选择。


注意:即使这个问题已经过时了,它仍然是相关的,所以我认为这个问题的答案值得更新。很抱歉使用仅链接的解决方案,所以我只添加了指向通常持久的目的地的链接:W3C和GitHub

您的数据库需求是否远远超出密钥/值存储?如果没有,我已经找到了许多用于基于本地浏览器的数据库抽象的javascript包。其中一个包是jStore:

http://code.google.com/p/jquery-jstore/

我最近用它来添加本地密钥/值存储。它有很好的文档记录,集成时间可以忽略不计——它通过其API支持一系列存储后端,包括闪存本地存储。

CouchDB是一个很好的解决方案——对于与您的问题不太一致的问题。查看couchphone mobile。不适用于严格意义上的网络应用程序,但如果您对规范有一定的灵活性,它可能会为您提供一个可以运行的数据库基础。

根据您对iOS上Safari的给定要求,除了WebSQL,别无选择。WebSQL在Opera和Blackberry等其他移动浏览器中也受支持。我不认为他们会删除对WebSQL的支持,即使他们有IndexedDB。不知怎的,它们是互补的。

另一方面,在浏览器存储战争中,IndexedDB赢得了胜利。IE和FF将仅具有IndexedDB。具有讽刺意味的是,FF在Sqlite之上实现了IndexedDB。

我想说的是IndexedDB不仅仅是一个键值存储。它有索引和事务。仅这两者就提供了SQL查询的几乎所有功能,包括联接、条件查询和排序。由于它的异步API,一开始并不明显。

IndexedDB的性能优于WebSQL。它更安全。对于javascript用例来说,它更灵活。最后,它更易于使用。

为了说明这种情况,我将使用我的库,但您可以直接使用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);
  });
});

这个代码的有趣之处在于它不涉及串行化。因此它非常快。

以下示例说明了友谊图查询友谊对象存储只有一个列出的索引字段friend_list。它使用人员对象存储密钥作为越界主键people对象存储有许多属性,其中包括location字段。该查询旨在查找认识meother_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使用排序合并算法来查找匹配的键,但这里显示了一个简单的嵌套循环连接算法。因此,表连接是可能的,但您必须对连接算法进行编码。但是,像Z字形合并这样的新算法比Sqlite更快,因为所有输入都经过排序,光标也可以前进,更重要的是,连接过程可以利用数据库中没有的外部知识。使用SQL时,联接操作是不透明的。

除此之外,IndexedDB还可以使用流和映射/减少处理等技术。





相关问题
CSS working only in Firefox

I am trying to create a search text-field like on the Apple website. The HTML looks like this: <div class="frm-search"> <div> <input class="btn" type="image" src="http://www....

image changed but appears the same in browser

I m writing a php script to crop an image. The script overwrites the old image with the new one, but when I reload the page (which is supposed to pickup the new image) I still see the old one. ...

Firefox background image horizontal centering oddity

I am building some basic HTML code for a CMS. One of the page-related options in the CMS is "background image" and "stretch page width / height to background image width / height." so that with large ...

Separator line in ASP.NET

I d like to add a simple separator line in an aspx web form. Does anyone know how? It sounds easy enough, but still I can t manage to find how to do it.. 10x!

热门标签