Оптимизация триггера SQLite - PullRequest
       5

Оптимизация триггера SQLite

1 голос
/ 08 сентября 2011

Это продолжение на основе этого вопроса об оптимизации запросов .

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

По сути, я хочу сохранить количество вхождений значения данного столбца в данную таблицу.

Следующая схема используется для хранения вхождений для каждого из значений:

CREATE TABLE valuecount (value text, count int)
CREATE INDEX countidx ON t (count DESC)
CREATE UNIQUE INDEX valueidx ON valuecount (value);

А вот триггер, с которым я тестировал:

CREATE TRIGGER counttrigger INSERT ON collection
  FOR EACH ROW
    BEGIN
      INSERT OR REPLACE INTO valuecount VALUES 
      (NEW.value, coalesce((SELECT count + 1 FROM count WHERE valuecount.query LIKE 
       NEW.value), 1));
    END;

Типичная вставка в таблицу collection содержит несколько сотен тысяч строк в одном операторе INSERT INTO ... SELECT ... (я объединяю данные из БД в другую).

Проблема в том, что с этим триггером вставка 300К строк занимает 4 часа вместо 300 мс ...

Есть ли способ достичь этого без ущерба для производительности?

Заранее спасибо за помощь,

Ответы [ 2 ]

2 голосов
/ 08 сентября 2011

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

Если это невозможно, есть ли способ избежать использования LIKE? Эта операция дороже, чем прямое сравнение.

0 голосов
/ 12 сентября 2011

Хорошо, так что казалось, что использование триггера было плохой идеей.

Поскольку я объединяю таблицу из разных баз данных, я выполнил переход в таблицу valuecount на основе содержимого таблицы, которую я объединяю, все в одном операторе перед вставкой.

Итак, вместо триггера, у меня просто запрос, который выглядит так, выполненный до моего INSERT INTO ... SELECT ... оператора:

INSERT OR REPLACE INTO valuecount
SELECT value, coalesce((SELECT count FROM valuecount WHERE valuecount.value = collection.value) + COUNT(value), COUNT(value))
FROM attached.collection GROUP BY value
...