Учитывая, что вы синхронизируете операции в миллисекундах , поведение, которое вы наблюдаете, имеет немало смысла.Сравнительный анализ одиночного запроса, выполняемого с такой степенью детализации времени, обычно не имеет смысла, если только вы не заинтересованы только в задержке, а не в пропускной способности.
Например, для конкретного запроса вы увидитесущественная разница в зависимости от того, есть ли в 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
(у вас его нет в вашем примере), будет ли найдена подходящая запись сразу или после просмотра всей таблицы, что повезло, поэтому серьезные изменения в завершении запросараз.