Массовая вставка базы данных Javascript - PullRequest
1 голос
/ 09 февраля 2010

Я пытаюсь вставить более 70000 строк в базу данных javascript (используя Chrome 5.0.317.2). Вставки занимают очень много времени. Реальная страница загружается через несколько секунд, и я вижу прогресс, поскольку процент увеличивается очень медленно, когда вставляется каждая строка. На вставку всех записей ушло около часа. Есть ли способ оптимизировать вставки или как-то начать с предварительно загруженной базы данных SQLite?

<script src="jquery.1.3.2.min.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript" charset="utf-8">
// Truncated to 1 row for example. There are really 76547 rows.
var zipcodes = var zipcodes = [{"city_name":"AMHERST","city_alias":"AMHERST","zipcode":"01002"}];
var db;
function openMyDatabase() {
    var shortName = 'mydb';
    var version = '1.0';
    var displayName = 'mydb';
    var maxSize = 65536;
    db = openDatabase(shortName, version, displayName, maxSize);
    db.transaction(
        function(transaction) {
            transaction.executeSql(
                'CREATE TABLE IF NOT EXISTS zipcode ' +
                '  (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, ' +
                '   city_name TEXT NOT NULL, ' +
                '   city_alias TEXT NOT NULL, ' +
                '   zipcode TEXT NOT NULL)'
            );
        }
    );
    $.each(zipcodes, function(i, zipcode) {
        insertZipcode(zipcode.city_name, zipcode.city_alias, zipcode.zipcode, i);
    });
}

function errorHandler(transaction, error) {
    alert('Oops. Error was '+error.message+' (Code '+error.code+')');
    return true;
}

function insertZipcode(cityName, cityAlias, zipcode, i) {
    db.transaction(
        function(transaction) {
            transaction.executeSql(
                'INSERT INTO zipcode (city_name, city_alias, zipcode) VALUES (?, ?, ?);',
                [cityName, cityAlias, zipcode],
                function(){
                    $('#counter').html((100 * i / zipcodes.length) + '%');
                },
                errorHandler
            );
        }
    );
    return false;
}

$(function() {
    openMyDatabase();
});
</script>

Решение: На стороне PHP я создал ассоциативный массив и использовал почтовый индекс в качестве ключа, а массив городов - в качестве значения, и прогнал его через json_encode и передал его в JavaScript. Что касается JavaScript, я смог очень быстро получить список городов для определенного почтового индекса, используя следующий код:

var zipcodes = {"55437":["MINNEAPOLIS","BLOOMINGTON"]}; //truncated
alert('Cities in 55437: ' + zipcodes['55437'].join(', '));

Ответы [ 6 ]

3 голосов
/ 09 февраля 2010

Если вы не можете переместить его на серверную часть (Javascript на самом деле не является инструментом для такой работы), определенно объедините несколько вставок, как предлагает Сурадж. 90% работы - это начало соединения, начало транзакции, завершение транзакции, закрытие соединения. 10% - фактические операции с БД.

transaction.executeSql('
            INSERT INTO zipcode (city_name, city_alias, zipcode) VALUES (?, ?, ?);
            INSERT INTO zipcode (city_name, city_alias, zipcode) VALUES (?, ?, ?);
            INSERT INTO zipcode (city_name, city_alias, zipcode) VALUES (?, ?, ?);
            ... //20-50 lines like this, maybe generated by a loop.
            ',[
            cityName1, cityAlias1, zipcode1,
            cityName2, cityAlias2, zipcode2,
            cityName2, cityAlias3, zipcode3,
            ... // a matching table, generated by a loop as well.
            ],
            ...
3 голосов
/ 09 февраля 2010

Одна проблема, которую я вижу, состоит в том, что вы пытаетесь вставить одну строку за раз, это может привести к большим накладным расходам при создании соединений и т. Д.

Было бы быстрее, если бы вы могли вставлять несколько строк (возможно, 20 или 50 за один выстрел) за один раз. Вы можете вставить несколько строк, используя эффективную процедуру или INSERT INTO или что-то еще.

1 голос
/ 02 августа 2011

У меня была точно такая же проблема. Я нашел сообщение в блоге, предоставляющее возможное решение. Вот ссылка: http://blog.heldes.com/html5/sqlite-class-for-html5-database/

Удачи

1 голос
/ 21 мая 2011

Что я сделал, чтобы преодолеть эту проблему, так это сначала создать строку, содержащую один trasanction со всеми его выполнениями, а затем запустить ее, используя javascript eval метод

jsonResponse = Ext.util.JSON.decode(result.responseText);
        jsonIndex = 0;
        var consulta = "DB.transaction(function (transaction){";
        while(jsonResponse[jsonIndex] != null){
            var ins = jsonResponse[jsonIndex].instruccion;
            ins = ins.replace(/&quot;/gi, "\"");
            consulta+= "transaction.executeSql('"+ins+"'); ";                
            jsonIndex++;
        }
        consulta+="});";
        eval(consulta);
1 голос
/ 09 февраля 2010

Почему бы не использовать предварительно загруженный XML вместо создания всех полей при загрузке веб-страницы?Таким образом вы сократите время загрузки, а время поиска может быть уменьшено за счет некоторого типа индексации, например, индексации по хеш-таблице или двоичного поиска.

Это уменьшит гибкость, что означает, что вам придется изменить XML и скомпилировать его с помощью инструмента - которого я не знаю, существует ли что-то подобное;но позволит повысить производительность, особенно если вы работаете на ограниченном устройстве, таком как IPhone.

0 голосов
/ 09 февраля 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...