Подсчет строк в БД sqlite - PullRequest
4 голосов
/ 24 ноября 2011

У меня есть sqlite db на встроенной платформе ARM под управлением Linux с несколько ограниченными ресурсами.Запоминающее устройство представляет собой карту microSD.Версия Sqlite - 3.7.7.1.Приложение, обращающееся к sqlite, написано на C ++.

Я хочу знать количество строк в нескольких таблицах через равные промежутки времени.В настоящее время я использую

select count(*) from TABLENAME;

, чтобы получить эту информацию.У меня проблемы с производительностью: когда размеры таблиц достигают определенной точки (~ 200 тыс. Строк), у меня возникает большая загрузка системы и iowait каждый раз, когда я проверяю размеры таблиц.

Когда я писал этоЯ, хотя поиск количества строк в таблице будет быстрым, поскольку он, вероятно, где-то хранится.Но теперь я подозреваю, что sqlite фактически просматривает все строки, и когда я прохожу точку, когда данные больше не помещаются в дисковый кеш, я получаю большую нагрузку ввода-вывода.Это примерно соответствует размеру базы данных и доступной памяти.

Может кто-нибудь сказать мне, ведет ли себя sqlite так, как я подозреваю?

Есть ли способ получить количество строк таблицы без выдачиколичество нагрузки?

РЕДАКТИРОВАТЬ : plaes спросил о макете таблицы:

CREATE TABLE %s (timestamp INTEGER PRIMARY KEY, offset INTEGER, value NUMERIC);

Ответы [ 3 ]

2 голосов
/ 24 ноября 2011

Имеет ли эта таблица индекс integer? Если нет, то добавьте один. В противном случае он должен отсканировать всю таблицу для подсчета предметов.

Это отрывок комментариев из кода SQLite, который реализует COUNT() синтаксический анализ и выполнение:

    /* If isSimpleCount() returns a pointer to a Table structure, then
    ** the SQL statement is of the form:
    **
    **   SELECT count(*) FROM <tbl>
    **
    ** where the Table structure returned represents table <tbl>.
    **
    ** This statement is so common that it is optimized specially. The
    ** OP_Count instruction is executed either on the intkey table that
    ** contains the data for table <tbl> or on one of its indexes. It
    ** is better to execute the op on an index, as indexes are almost
    ** always spread across less pages than their corresponding tables.
    */
    [...]
    /* Search for the index that has the least amount of columns. If
    ** there is such an index, and it has less columns than the table
    ** does, then we can assume that it consumes less space on disk and
    ** will therefore be cheaper to scan to determine the query result.
    ** In this case set iRoot to the root page number of the index b-tree
    ** and pKeyInfo to the KeyInfo structure required to navigate the
    ** index.
    **
    ** (2011-04-15) Do not do a full scan of an unordered index.

Кроме того, вы можете получить дополнительную информацию о вашем запросе с помощью EXPLAIN QUERY PLAN.

1 голос
/ 26 ноября 2011

Из всей информации, которую я собрал, count (), видимо, действительно нуждается в сканировании таблицы. Как отметил Плейс, это быстрее, если подсчет выполняется по целочисленному индексируемому столбцу, но сканирование индекса по-прежнему необходимо.

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

0 голосов
/ 30 апреля 2015

Вот 2 возможных метода обхода количества строк в таблице (с оговорками), которые не вызывают сканирование таблицы / индекса:

  1. Примечание для таблиц, в которых вы можете использовать INTEGER PRIMARY KEY AUTOINCREMENT в качествеПервичный ключ, вы можете получить счет из мета-таблицы sqlite_sequence sqlite:

    выберите имя, seq из sqlite_sequence

seq будет содержать либо последний идентификатор, либо следующийid (думаю последнее, но не уверен).

«выбрать максимум (pkid) из таблицы», который, вероятно, будет выполнять поиск по индексу вместо сканирования (и также будет точным только для таблиц без удалений).

Зная это,если ваш сценарий использования включает в себя УНИКАЛЬНЫЕ удаления для таблиц, на которых вы можете использовать AUTOINCREMENT, вы можете сделать гибрид решения на основе триггера и считать только удаленные строки (что, вероятно, будет меньше учета, чем подсчет вставок для большинства сценариев).Однако, если вы вставите и удалите одну и ту же строку дважды, это также не сработает.

...