INTEGER PRIMARY KEY против rowid в SQLite - PullRequest
0 голосов
/ 04 июня 2018

Я пытаюсь импортировать некоторые пространственные данные (OSM) в базу данных SQLite.Ссылка на SQLite гласит, что INTEGER PRIMARY KEY становится псевдонимом для rowid (если WITHOUT ROWID не указан).Просто чтобы быть уверенным, я создал свою главную таблицу двумя различными способами:

CREATE TABLE points (tags BLOB NOT NULL,
                     lon INTEGER NOT NULL,
                     lat INTEGER NOT NULL)

против

CREATE TABLE points (id INTEGER PRIMARY KEY,
                     tags BLOB NOT NULL,
                     lon INTEGER NOT NULL,
                     lat INTEGER NOT NULL)

Я ожидал таких же результатов, но после запуска приложения дважды мои дваФайлы базы данных явно различаются по размеру: версия с явным первичным ключом занимает примерно 100 МБ дополнительного дискового пространства (1,5 ГБ против 1,4 ГБ).Мои операторы вставки равны, кроме того факта, что один использует «id», а другой «rowid» в качестве столбца назначения для идентификатора точки.

Кто-нибудь знает, откуда взялась эта огромная разница в размере?Заранее спасибо.

1 Ответ

0 голосов
/ 05 июня 2018

Может показаться, что для каждой строки есть псевдоним для rowid байта (я думаю), который, как мне кажется, объясняется следующим образом: -

Когда таблица SQL включаетстолбец INTEGER PRIMARY KEY (который содержит псевдоним rowid), затем этот столбец появляется в записи как значение NULL.SQLite всегда будет использовать ключ b-дерева таблицы, а не значение NULL при обращении к столбцу INTEGER PRIMARY KEY. Формат файла базы данных - 2.3.Представление таблиц SQL .

1 байт на строку выглядит довольно близко в соответствии со следующим тестированием: -

Были созданы две базы данных с двумя разными таблицами,загружено 1 000 000 миллионов строк с использованием следующего SQL: -

для первого: -

DROP TABLE IF EXISTS points;
CREATE TABLE IF NOT EXISTS points (tags BLOB NOT NULL, lon INTEGER NOT NULL, lat INTEGER NOT NULL);
WITH RECURSIVE counter(tags,lon,lat) AS (SELECT x'00000000', 0,0 UNION ALL SELECT tags, random() AS lon, random() AS lat FROM counter LIMIT 1000000)
INSERT INTO points (tags,lon,lat) SELECT * FROM counter;
SELECT * FROM points;
VACUUM

для второго (с псевдонимом rowid): -

DROP TABLE IF EXISTS points;
CREATE TABLE IF NOT EXISTS points (id INTEGER PRIMARY KEY, tags BLOB NOT NULL, lon INTEGER NOT NULL, lat INTEGER NOT NULL);
WITH RECURSIVE counter(tags,lon,lat) AS (SELECT x'00000000', 0,0 UNION ALL SELECT tags, random() AS lon, random() AS lat FROM counter LIMIT 1000000)
INSERT INTO points (tags,lon,lat) SELECT * FROM counter;
SELECT * FROM points;
VACUUM

Результирующие размеры файлов составляли 29484 КБ и 30600 КБ соответственно.

При разнице 30600 - 29484 = 1116 умножьте это на 1024 = 1142784 (не так уж далеко от 1 000 000 строк, страниц и свободного пространства, вероятно,с учетом расхождений).

  • Обратите внимание, что команда VACUUM не изменила (поскольку они были новыми таблицами, не ожидалось, что они будут).
...