Длина имени таблицы в sqlite влияет на производительность. Почему?

Я заметил, что длина имен таблиц влияет на производительность при создании этих таблиц. Вот пример кода, который воспроизводит проблему:

#include <stdio.h>
#include <assert.h>
#include "sqlite3.h"

int main() {
  int i, sr;
  char table_query[1000];
  sqlite3* db;

  sr = sqlite3_open("test.db", &db);
  assert(sr == SQLITE_OK);

  sr = sqlite3_exec(db, "PRAGMA synchronous=OFF", NULL, NULL, NULL);
  assert(sr == SQLITE_OK);

  sr = sqlite3_exec(db, "PRAGMA journal_mode=OFF", NULL, NULL, NULL);
  assert(sr == SQLITE_OK);

  sr = sqlite3_exec(db, "PRAGMA temp_store=MEMORY", NULL, NULL, NULL);
  assert(sr == SQLITE_OK);

  sr = sqlite3_exec(db, "BEGIN EXCLUSIVE TRANSACTION;", NULL, NULL, NULL);
  assert(sr == SQLITE_OK);

  for (i = 0; i < 10000; ++i) {
  #ifdef LONG_NAMES
   sprintf(table_query, "CREATE TABLE `TABLE_%d_AKLKEKABCDEFGHIJK4C6F766520416C6C20546865205061696E204177617920496E636C204B796175202620416C626572742052656D69782020434452` (content);", i);
  #else
   sprintf(table_query, "CREATE TABLE `TABLE_%d` (content);", i);
  #endif

   sr = sqlite3_exec(db, table_query, NULL, NULL, NULL);
   assert(sr == SQLITE_OK);

  }

  sr = sqlite3_exec(db, "END TRANSACTION;", NULL, NULL, NULL);
  assert(sr == SQLITE_OK);

  sr = sqlite3_close(db);
  assert(sr == SQLITE_OK);

  return 0;
}

Для компиляции:
gcc main.c sqlite3.c -O3 -DLONG_NAMES -DNDEBUG
gcc main.c sqlite3.c -O3 -DNDEBUG

На моей машине при использовании относительно коротких имен таблиц, таких как TABLE_{table #}, создание базы данных с 10 000 таблиц занимает примерно 14 секунд. Эти имена таблиц варьируются от 7 до максимум 11 символов.

При использовании относительно длинных имен таблиц, таких как TABLE_{table #}_{some unique identifying name that adds 120 or so characters}, создание базы данных с 10 000 таблиц занимает примерно 60 секунд.

Создание БД с длинными именами таблиц заняло в 4 раза больше времени!

Почему это так? Это ожидаемое поведение или ошибка?

А поскольку создание таблиц с длинными именами негативно влияет на производительность, это заставляет меня задаться вопросом, не повлияет ли это негативно на производительность запросов к такой базе данных. Этот ответ SO кажется, что ответ "нет" в отношении MySQL, но никаких ссылок не дается.

Мысли?

PS: я использую последнюю объединенную версию sqlite (3.8)


person BigMacAttack    schedule 03.09.2013    source источник
comment
Являются ли 10000 таблиц со 120-символьными именами реальным вариантом использования?   -  person CL.    schedule 04.09.2013
comment
@CL Да. Это реальный вариант использования. Хотя можно поместить все эти данные в одну таблицу, это сильно усложняет другие аспекты моей реализации. Я хотел бы понять, можно ли что-то сделать, чтобы исправить эту проблему с производительностью имени таблицы, прежде чем сдаться и перейти к более плоской структуре базы данных.   -  person BigMacAttack    schedule 04.09.2013
comment
Между прочим, мне пришлось добавить -pthread -ldl в RedHat 6.4 с GCC 4.4.7, чтобы правильно связать этот пример с SQLite 3.8.0.2. С короткими именами требуется 10,7 с (3 прогона) для создания 11 МБ test.db, а для создания 15 МБ test.db с добавлением -DLONG_NAMES требуется 27,5 с (3 прогона тоже).   -  person ddevienne    schedule 04.09.2013


Ответы (2)


При более длинных именах таблиц результирующий пустой файл базы данных становится в 4 раза больше, поскольку более длинные имена таблиц занимают больше места в схеме. Неудивительно, что SQLite требуется в 4 раза больше времени, чтобы написать в 4 раза больше контента.

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

person Richard Hipp    schedule 04.09.2013
comment
Неудивительно, что SQLite требуется в 4 раза больше времени, чтобы написать в 4 раза больше контента. - Не уверен, что согласен с этим утверждением. Если вместо этого я разработаю базу данных для использования одной таблицы и опишу имена таблиц в виде строк, создание базы данных будет намного быстрее. На порядок быстрее. Проблема производительности, которую я описываю, конкретно связана с созданием таблиц. Более длинные записи в строках не так сильно влияют на производительность, как более длинные имена таблиц. - person BigMacAttack; 06.09.2013

Более длинные имена таблиц занимают больше места в системной таблице sqlite_master (сравните размеры файлов). Когда SQLite просматривает эту системную таблицу для поиска таблицы (или для проверки того, существует ли уже новое имя таблицы), необходимо прочитать и сравнить больше данных.

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

person CL.    schedule 04.09.2013