SQLite противоречивая производительность - PullRequest
4 голосов
/ 06 апреля 2011

У меня есть рукописная ORM, построенная поверх объектной системы Qt.Я тестирую его с помощью SQLite и вижу странные проблемы с производительностью.В базе данных хранится около 10 тыс. Объектов.Объекты загружаются один за другим с отдельными запросами.

Один из запросов демонстрирует изменения во времени выполнения: от 1 мс до 10 в зависимости от идентификатора первичного ключа.Это время также включает в себя некоторые операции, выполняемые модулем Qt Sql.

Запрос очень прост и выглядит следующим образом (id = 100 отличается между запросами):

SELECT * FROM t1, t2 WHERE t1.id = 100 AND t2.id = 100

заставить один и тот же запрос выполнять в 10 раз хуже в зависимости от идентификатора строки?

1 Ответ

2 голосов
/ 08 апреля 2011

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

Например, для конкретного запроса вы увидитесущественная разница в зависимости от того, есть ли в t1 строки отображения, поскольку это определит, должен ли SQLite вообще беспокоиться о t2.

Даже при выполнении точно тот же запрос будетВ зависимости от кеша файловой системы ОС, планировщика процессов, кеша SQLite, положения пластин и головок жесткого диска и других факторов, можно получить разные результаты.

Более конкретно, есть две возможности:

А.t1.id и t2.id проиндексированы

Это наиболее вероятный случай - я ожидаю, что столбец таблицы с меткой id будет проиндексирован.

Большинство механизмов SQL, включая SQLiteиспользуйте некоторые вариации B-дерева для каждого индекса.На SQLite каждый узел дерева представляет собой отдельную страницу в файле БД.С вашим конкретным запросом SQLite придется пройти:

  • Некоторые страницы t1.id индекса
  • Некоторые страницы t2.id индекса
  • Страницы БД, в которых содержатся совпадающие строки из обеих таблиц.

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

Кроме того, если ваша БД действительно мала, онаобычно не помещается в кэш SQLite3, и только попадания в кеш и пропуски могут объяснять довольно серьезные различия во времени, необходимом для выполнения одного запроса: пропадание кеша SQLite вызывает чтение из файловой системы, что может легко привести к процессу БДбыть перенесены ОС в пользу другого процесса.

B.t1.id и t2.id не проиндексированы

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

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