2017-02-09 5 views
0

Установка не может быть проще:H2 странность производительности базы данных --- или как эффективно `COUNT (*)`

  • версия H2 1.3.176
  • одна таблица, 10 колонн из которых два являются бит длиной 300 и 3500 символов, типичная длина значения
  • Простой запрос: select count(*) from requestrepository where request_type = 'ADD'
  • Указатель находится в запрашиваемом столбце.
  • Запрашиваемая колонка - это только varchar (20) (то есть не один из более длинных)
  • В столбце «Запрос» содержатся только два разных значения: один появляется в 200 тыс. Раз, а другой появляется 12 миллионов раз.
  • DB сбегает в SSD, текущее серверное оборудование, текущий Java 8 (варьировался немного, но никаких изменений в результате)

Что я: (0) запустить analyze (1) удаление одной строки по ключевое поле, (2) вставить одну строку для только что удаленной клавиши, (3) запустить приведенный выше запрос, подсчитать до 10 и повторить.

Что я вижу: Запрос упоминавшееся выше занимает от 3 до 5 секунд каждый раз и explain analyze говорит:

SELECT 
    COUNT(*) 
FROM PUBLIC.REQUESTREPOSITORY 
    /* PUBLIC.IX_REQUESTS: REQUEST_TYPE = 'ADD' */ 
    /* scanCount: 12098748 */ 
WHERE REQUEST_TYPE = 'ADD' 
/* 
REQUESTREPOSITORY.IX_REQUESTS read: 126700 
*/ 

Я попробовал ту же БД на разных машинах, аппаратных/Linux/ССД, VM/Windows/netapp, но тенденция всегда одна и та же: count(*) занимает слишком долго (?).

И это то, о чем я не уверен. Можно ли ожидать, что это займет много времени? Я бы подумал, что, по крайней мере, для второго раунда, кеши заполняются, и это должно быть намного быстрее, но explain analyze всегда отображает 126700 просмотров.

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

EDIT (не уверен, что это скорее ответит) Между тем мы пробовали широкий спектр вещей, включая mvstore, 1.4.x, параллельные потоки, компьютеры с разными дисками, Linux, Windows. Ситуация всегда одна и та же. Возьмите более 10 или 12 миллионов строк, столбец varchar с тремя значениями состояния, что-то вроде PROCESSING, ADD, DELETE, индекс в столбце и одно состояние, чрезмерно перепредставленное: тогда что-то вроде count(*) where colname='ADD' занимает от 1 до и многих секунд после каждого обновления Таблица.

Чтобы предотвратить возникновение проблемы, мы, наконец, исправили наш собственный код, который сделал три count(*), по одному для каждого состояния, а не один с group by и запускался каждые 5 секунд, а не только по требованию. Конечно, не самый большой дизайн, который у нас был.

Единственное оправдание, которое у меня есть, это то, что я все еще удивляюсь, что count(*) так долго в такой настройке занимает. Моя догадка заключается в том, что счетчик должен вычисляться по индексу, действительно рассчитывая после обновления, тогда как я ожидал, что счетчик можно просто прочитать где-нибудь в структуре данных. (Никакой критики, я для себя, конечно, не смог бы реализовать БД.)

+0

Пробовал ли вы использовать последнюю версию H2 (с форматом MVStore)? –

ответ

0

Не уверен насчет H2, но вы пробовали COUNT(request_type) вместо COUNT(*)?

Стандарт COUNT(*) стандарта SQL имеет тенденцию занять много времени, так как для полного заполнения таблицы требуется отфильтровать строки, которые состоят только из значений NULL.

Использование COUNT() на одной проиндексированной колонке может ускорить процесс. Таким образом, никакая строка таблицы не должна быть прочитана, так как индекса достаточно, чтобы решить, имеет ли значение столбца значение NULL.

Смежные вопросы