HTML5 IndexedDB、Web SQL数据库和浏览器大战

vwoqyblh  于 2022-12-09  发布在  IndexedDB
关注(0)|答案(6)|浏览(403)

我正在开发一个具有离线数据库存储要求的Web应用程序。长话短说,该应用程序应该能够在以下平台上运行:

  • 主要桌面浏览器之一,首选Chrome
  • iOS上的Safari
  • Android原生浏览器(基于V8和WebKit)

所以问题是选择哪种技术:IndexedDB还是Web SQL数据库?
关于Web SQL数据库,一方面,它已经准备好在上述任何场景中使用。另一方面,Mozilla声明Firefox永远不会实现它,根据HTML5 working draft规范,该规范已经陷入僵局:
这一规范已陷入僵局:所有感兴趣的实现者都使用了相同的SQL后端(Sqlite),但是我们需要多个独立的实现来沿着标准化的道路前进。在另一个实现者有兴趣实现这个规范之前,SQL方言的描述一直被保留为对Sqlite的简单引用,这对于一个标准来说是不可接受的。如果你是一个对实现独立的SQL后端感兴趣的实现者,请与编辑联系,以便他能够为该方言编写一个规范,从而使该规范向前发展。
IndexedDB是Mozilla提倡的替代方案,但它只会出现在Firefox 4中。微软对此感兴趣,Chrome也会支持它。我对苹果关于IndexedDB的计划一无所知。
我个人倾向于选择Web SQL数据库,但只是因为我习惯于SQLite,我喜欢SQL的强大功能和表达能力,我理解关系模型。
这就是说,我恐怕押错了赌注。假设对Web SQL数据库的支持将继续存在,即使IndexedDB成为标准,这是否安全?
(关于CouchDB的注解:你是否也将其视为一种替代方案?)

xxls0lw8

xxls0lw81#

嗯,就像所有的计算一样,游戏是“抽象”的。
如果你能找到一个既能处理SQL存储又能处理键/值存储的合适的层,那么,理想的情况下,你就可以从问题中分离出来,并且可以支持特定浏览器上的适当实现。如果你的数据模型和访问模式不符合最低的公分母(例如,k/v存储),那么你的问题就基本解决了。
如果您可以使用这两种存储中的任何一种,那么就在一个合适的访问层上工作,并从那个方向解决问题。
注意,仅仅因为在后端有一个k/v存储并不意味着您必须将数据建模为k/v模型。实际上,后端的所有DB都是一个k/v存储。如果您没有海量的数据,你可以做很多事情。对于大量的数据,您可能不得不跳过的限制可能会降低性能,而对于少量的数据,您可能不会看到这一点。数据。一切取决于。

yvt65v4c

yvt65v4c2#

考虑到只有WebSQL支持您列出的所有三个要求,您的选择难道不应该很简单吗?您对Safari或Android的开发路线图没有深入了解,因此使用您现有的开发路线图。

8gsdolmq

8gsdolmq3#

我在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表进行存储操作。
因此,如果你大量使用那些类型的功能,你可能想看看其他地方。
哦,为了完全透明,烘焙商品是由你真正维护的:)。

mrwjdhj3

mrwjdhj34#

我的建议是使用IndexDB,因为有IndexDB Polyfill可用。
所有支持WebSQL的浏览器都可以通过这种方式支持IndexDB API。反之则很难实现,所以如果你想访问所有了解一些DB API的浏览器,IndexDB是目前最好的选择。
注意:即使这个问题已经过时了,它仍然是相关的,所以我认为这个问题的答案值得更新。对不起,只有链接的解决方案,所以我只添加了链接到通常持久的目的地:W3C和GitHub

klh5stk1

klh5stk15#

您的数据库需求是否远远超出了键/值存储的范围?如果不是,我已经找到了许多用于基于本地浏览器的数据库抽象的javascript包。jStore就是这样一个包:
http://code.google.com/p/jquery-jstore/
我最近使用它来添加本地键/值存储。它有很好的文档记录,集成时间可以忽略不计--它通过其API支持一系列存储后端,包括闪存本地存储。
CouchDB是一个很好的解决方案--对于一个与您的问题不太一致的问题。请查看couchone mobile。它不适用于严格意义上的“Web应用程序”,但如果您对规范有一定的灵活性,它可能会提供一个可以运行的数据库基础。

8e2ybdfx

8e2ybdfx6#

根据你对iOS上Safari的要求,除了WebSQL之外别无选择。WebSQL在其他移动的浏览器上也有支持,比如Opera和Blackberry。我不认为他们会取消WebSQL支持,即使他们有IndexedDB。不知何故,他们是互补的。
另一方面,在浏览器存储大战中,IndexedDB已经永远赢了,IE和FF只会有IndexedDB,一个具有讽刺意味的事实是FF在Sqlite之上实现了IndexedDB。
我想说的是IndexedDB不仅仅是一个键值存储,它还有索引和事务,仅这两个就提供了SQL查询的几乎所有特性,包括连接、条件和排序,由于它的异步API,一开始并不明显。
IndexedDB的性能优于WebSQL,安全性更高,对javascript用例更灵活,使用更方便。
为了说明这种情况,我将使用my library中的伪代码,但您可以直接使用IndexedDB API:
“people”存储具有索引字段“name”和列表索引字段“hobby”。在JSON中,

people = {
  name: 'Foo Bar',
  email: 'foo@bar.com'
  hobby: ['camping', 'swimming']
};

从爱好为'camping''人'中检索姓名

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字段。该查询用于查找认识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使用排序合并算法来查找匹配的键,但这里显示了一个简单的嵌套循环连接算法。因此,表连接是可能的,但您必须编写连接算法。但像zigzmerge这样的新算法比Sqlite更快,因为所有输入都是排序的。游标也可以前进,更重要的是连接过程可以利用数据库中没有的外部知识。2使用SQL,连接操作是不透明的。
除此之外,还可以使用IndexedDB技术,如流和Map/减少处理。

相关问题