HTML5 IndexedDB, база данных Web SQL и войны браузеров - PullRequest
44 голосов
/ 19 октября 2010

Я начинаю разработку веб-приложения с требованиями к автономному хранилищу базы данных.Короче говоря, приложение должно работать на:

  • Один из основных настольных браузеров, предпочитаемый Chrome
  • Safari на iOS
  • собственный браузер Android (на основе V8 и WebKit)

Итак, вопрос в том, какую технологию выбрать: IndexedDB или базу данных Web SQL?

Что касается базы данных Web SQL, с одной стороны, она готова киспользуется в любом из вышеперечисленных сценариев.С другой стороны, Mozilla заявляет, что Firefox никогда не реализует его, и согласно рабочему проекту HTML5 спецификация зашла в тупик:

Эта спецификация зашла в тупик: всеЗаинтересованные разработчики использовали один и тот же SQL-бэкэнд (Sqlite), но нам нужно несколько независимых реализаций для продвижения по пути стандартизации.Пока другой разработчик не заинтересован в реализации этой спецификации, описание диалекта SQL оставлено просто как ссылка на Sqlite, что неприемлемо для стандарта.Если вы являетесь разработчиком, заинтересованным в реализации независимого бэкэнда SQL, пожалуйста, свяжитесь с редактором, чтобы он мог написать спецификацию для диалекта, что позволит этой спецификации двигаться вперед.

IndexedDB является альтернативойот Mozilla, но только в Firefox 4. Microsoft заинтересована, и Chrome также поддержит ее.Я ничего не знаю о планах Apple в отношении IndexedDB.

Я лично склонен выбирать базу данных Web SQL, но только потому, что я привык к SQLite, мне нравится мощь и выразительность SQL, и я понимаю реляционныемодель.IndexedDB для меня - неопределенность.

Тем не менее, я боюсь ставить не на ту лошадь.Можно ли предположить, что поддержка базы данных Web SQL будет продолжать существовать, даже если IndexedDB станет стандартом?

(Примечание по CouchDB: вы также рассматриваете его как альтернативу?)

Ответы [ 6 ]

24 голосов
/ 28 октября 2010

Ну, как и во всех вычислениях, игра является "абстракцией".

Если вы можете создать адекватный уровень, который работает как с хранилищем SQL, так и с хранилищем ключей / значений, то в идеале вы изолированы от проблемы и можете поддерживать соответствующую реализацию в конкретном браузере. Если ваша модель данных и шаблоны доступа не соответствуют наименьшему общему знаменателю (т. Е. Хранилище k / v), то это в значительной степени решает вашу проблему прямо здесь.

Если вы можете использовать любой магазин, тогда работайте на достойном уровне доступа и подходите к проблеме с этой стороны.

Имейте в виду, только то, что у вас есть хранилище k / v на заднем конце, не означает, что вы должны моделировать свои данные как только модель k / v. По сути, вся БД на бэкэнде - это хранилище k / v. Если у вас нет безумного количества данных, вы можете сделать много вещей. При большом количестве данных обручи, которые вам, возможно, придется перепрыгнуть, могут снизить производительность, которую вы можете не увидеть при меньшем количестве данных. Все зависит.

14 голосов
/ 20 октября 2010

Учитывая, что только WebSQL поддерживает все три перечисленных вами требования, разве ваш выбор не должен быть простым? У вас нет понимания плана развития Safari или Android, поэтому используйте то, что у вас есть.

6 голосов
/ 09 августа 2013

Я рекомендую перейти на IndexDB , потому что есть IndexDB Polyfill .

Все браузеры, поддерживающие WebSQL, могут поддерживать IndexDB API таким образом.Обратный путь будет очень трудным для реализации, поэтому, если вы хотите охватить все браузеры, которые знают о каком-либо API БД, IndexDB является лучшим выбором на сегодняшний день.


Примечание. Даже если этот вопрос старыйэто все еще актуально, поэтому я думаю, что ответы на этот вопрос заслуживают обновления.И извините за решение только для ссылок, поэтому я добавил только ссылки на обычно продолжительные пункты назначения: W3C и GitHub

6 голосов
/ 28 октября 2010

Нужна ли ваша база данных значительно больше, чем хранилища ключей / значений? Если нет, я нашел несколько пакетов javascript для абстракции базы данных в локальном браузере. Одним из таких пакетов является jStore:

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

Я недавно использовал его для добавления локального хранилища ключей / значений. Он хорошо документирован, а время интеграции было незначительным - он поддерживает массив бэкэндов хранилища, включая локальное флэш-хранилище, через API.

CouchDB - отличное решение для проблемы, которая не совсем совпадает с вашей. Проверьте мобильный телефон . Не только для «веб-приложений», но может обеспечить основу базы данных, с которой вы могли бы работать, если у вас есть некоторая гибкость со спецификацией.

5 голосов
/ 09 июля 2016

Я отвечаю на это в 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 поддерживается вашими по-настоящему :).

5 голосов
/ 11 ноября 2012

С вашим заданным требованием Safari на iOS, нет альтернативы, кроме WebSQL.WebSQL поддерживается в других мобильных браузерах, таких как Opera и Blackberry.Я не думаю, что они уберут поддержку WebSQL, даже если у них есть IndexedDB.Как-то они дополняют друг друга.

С другой стороны, в войне хранилищ браузера, IndexedDB выиграл навсегда.IE и FF будут иметь только IndexedDB.Забавно, что FF реализует IndexedDB поверх Sqlite.

Я хотел бы сказать, что IndexedDB - это больше, чем просто хранилище значений ключей.У него есть индекс и транзакция.Эти только два делают практически все функции SQL-запросов, включая объединение, условное и сортировку.Сначала это не очевидно из-за его асинхронного API.

Производительность IndexedDB лучше, чем WebSQL.Это более безопасно.Это более гибкий вариант использования JavaScript.Наконец, его проще использовать.

Чтобы проиллюстрировать этот случай, я буду использовать код sudo из моей библиотеки , но вы можете напрямую использовать IndexedDB API:

The 'Магазин людей имеет индексное поле «имя» и индексированное поле списка «хобби».В 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 использует алгоритм сортировки слиянием для поиска подходящих ключей, но здесь показан наивный алгоритм объединения вложенных циклов.Таким образом, объединение таблиц возможно, но вы должны кодировать алгоритм объединения.Но более новые алгоритмы, такие как зигзагообразное слияние, быстрее, чем это возможно в Sqlite, потому что все входные данные отсортированы, курсоры могут продвигаться вперед и, что более важно, процесс объединения может использовать внешние знания, которых нет в базе данных.В SQL операция соединения непрозрачна.

Помимо IndexedDB, могут использоваться такие методы, как потоковая передача и обработка отображения / сокращения.

...