Установка не может быть проще: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(*)
так долго в такой настройке занимает. Моя догадка заключается в том, что счетчик должен вычисляться по индексу, действительно рассчитывая после обновления, тогда как я ожидал, что счетчик можно просто прочитать где-нибудь в структуре данных. (Никакой критики, я для себя, конечно, не смог бы реализовать БД.)
Пробовал ли вы использовать последнюю версию H2 (с форматом MVStore)? –