Оптимизирует ли индекс sqlite, сохраняя максимальное и минимальное значения столбца int? - PullRequest
0 голосов
/ 04 января 2019

Мне было любопытно, если sqlite index хранит максимальные и минимальные значения столбца, чтобы оптимизировать запросы к нему.Я думал, что если бы у нас был большой файл с миллионами записей, если бы в индексе хранились максимальное и минимальное значения, а у нас было больше или меньше критериев в столбце, чем запрос мог бы мгновенно сказать нам, что запись не существуети не нужно беспокоиться о поиске файла БД в первую очередь.Может ли кто-нибудь узнать, хранятся ли max и min в индексе БД в чем-то таком, как sqlite?

Ответы [ 2 ]

0 голосов
/ 05 января 2019

Минимальное и максимальное значения не хранятся отдельно.

Однако они являются первой и последней записями в индексе, поэтому их можно быстро прочитать.Это называется оптимизацией MIN / MAX :

Запросы, содержащие одну агрегатную функцию MIN () или MAX (), аргумент которой является крайним левым столбцом индекса, можетбыть удовлетворенным выполнением единственного поиска индекса, а не сканированием всей таблицы.Примеры:

SELECT MIN(x) FROM table;
SELECT MAX(x)+1 FROM table;

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

0 голосов
/ 04 января 2019

Насколько мне известно, SQlite не хранит такие значения независимо от данных.Однако вы можете легко сделать это, создав таблицу для хранения минимальных и максимальных значений и каждый раз, когда вставляется строка.

Обновления и удаления могут, однако, занимать больше времени, когда необходимо изменить минимальное или максимальное значение..

Вероятно, было бы более эффективно хранить также и rowid строк.

Таблица, такая как: -

CREATE TABLE IF NOT EXISTS minmax_store(max_value INTEGER, max_rowid INTEGER, min_value INTEGER, min_rowid INTEGER);

демо, которое может подойти.Он использует триггеры для ведения таблицы minmax_store : -

DROP TABLE IF EXISTS mydata;
CREATE TABLE IF NOT EXISTS mydata(id INTEGER PRIMARY KEY, myvalue INTEGER);
DROP TABLE IF EXISTS minmax_store;
CREATE TABLE IF NOT EXISTS minmax_store (max_value INTEGER, max_rowid INTEGER, min_value INTEGER, min_rowid INTEGER);
INSERT INTO minmax_store VALUES(-9223372036854775806,-1,9223372036854775807,-1);
DROP TRIGGER IF EXISTS maintain_minmax_after_insert;
CREATE TRIGGER IF NOT EXISTS maintain_minmax_after_insert AFTER INSERT ON mydata
    BEGIN
        UPDATE minmax_store SET max_value = new.myvalue, max_rowid = new.id WHERE max_value < new.myvalue;
      UPDATE minmax_store SET min_value = new.myvalue, min_rowid = new.id WHERE min_value > new.myvalue;    
    END
;
DROP TRIGGER IF EXISTS maintain_minmax_after_delete;
CREATE TRIGGER IF NOT EXISTS maintain_minmax_after_delete AFTER DELETE ON mydata 
    WHEN (SELECT max_value FROM minmax_store) = old.myvalue OR (SELECT min_value FROM minmax_store) = old.myvalue
    BEGIN
        UPDATE minmax_store 
            SET max_value = (SELECT max(myvalue) FROM mydata), max_rowid = (SELECT rowid FROM mydata ORDER BY myvalue DESC LIMIT 1),
            min_value = (SELECT min(myvalue) FROM mydata), min_rowid = (SELECT rowid FROM mydata ORDER BY myvalue ASC LIMIT 1);
    END
;
DROP TRIGGER IF EXISTS maintain_minmax_after_update;
CREATE TRIGGER IF NOT EXISTS maintain_minmax_after_update AFTER UPDATE ON mydata
    WHEN (SELECT max_value FROM minmax_store) = old.myvalue 
        OR (SELECT min_value FROM minmax_store) = old.myvalue  
        OR (SELECT max_value FROM minmax_store) < new.myvalue
      OR (SELECT min_value FROM minmax_store) > new.myvalue
    BEGIN
        UPDATE minmax_store
            SET max_value = (SELECT max(myvalue) FROM mydata), max_rowid = (SELECT rowid FROM mydata ORDER BY myvalue DESC LIMIT 1),
            min_value = (SELECT min(myvalue) FROM mydata), min_rowid = (SELECT rowid FROM mydata ORDER BY myvalue ASC LIMIT 1);
  END
;   

INSERT INTO mydata (myvalue) VALUES(1),(4),(6),(7),(8),(3),(5),(0),(9),(100),(200),(55),(66),(33),(4421);
SELECT * FROM minmax_store;

SELECT *, 
    CASE 
        WHEN myvalue = (SELECT max_value FROM minmax_store) THEN 'MAX VALUE HERE' ELSE '' END AS isrowmaxvalue,
    CASE
        WHEN myvalue = (SELECT min_value FROM minmax_store) THEN 'MIN VALUE HERE' ELSE '' END AS isrowminvalue
    FROM mydata;

DELETE FROM mydata WHERE myvalue = (SELECT min(myvalue) FROM mydata);

SELECT * FROM minmax_store;
SELECT *, 
    CASE 
        WHEN myvalue = (SELECT max_value FROM minmax_store) THEN 'MAX VALUE HERE' ELSE '' END AS isrowmaxvalue,
    CASE
        WHEN myvalue = (SELECT min_value FROM minmax_store) THEN 'MIN VALUE HERE' ELSE '' END AS isrowminvalue
    FROM mydata;

UPDATE mydata SET myvalue = (SELECT max_value FROM minmax_store) + 10 WHERE myvalue = (SELECT min_value FROM minmax_store);
SELECT * FROM minmax_store;
SELECT *, 
    CASE 
        WHEN myvalue = (SELECT max_value FROM minmax_store) THEN 'MAX VALUE HERE' ELSE '' END AS isrowmaxvalue,
    CASE
        WHEN myvalue = (SELECT min_value FROM minmax_store) THEN 'MIN VALUE HERE' ELSE '' END AS isrowminvalue
    FROM mydata

Первый запрос возвращает (таблица minmax_store): -

enter image description here

Второй запрос возвращает: -

enter image description here

Третий запрос после удаления минимальной строки (значение 0), показывает измененные minmax_store как: -

enter image description here

Возвращает четвертый запрос (тот же, что и второй): -

enter image description here

Пятый запрос после строки с минимальным значением изменяется на максимальное значение + 10 (4431), показывает измененное значение minmax_store as: -

enter image description here

Возвращает шестой запрос (так же, как 2-й и 4-й запросы): -

enter image description here

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