2012-12-03 2 views
1

У меня есть база данных PostgreSQL, которая содержит много строк ~ 160 000 000. База данных представляет собой набор сетевых журналов. Существует столбец, называемый временем, которое является отметкой времени. В основном для каждого уникального времени есть журнал для каждой машины в сети. Таким образом, существует несколько строк с одинаковой меткой времени. т.е.Проблема производительности индекса PostgreSQL

time ip    value 
2:00 192.168.1.1 5 
2:00 192.168.1.2 4 
2:00 192.168.1.3 5 
3:00 192.168.1.1 3 
3:00 192.168.1.2 5 
3:00 192.168.1.3 2 
etc  etc 

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

i.e. select * from networklogs where time = '2:00' and value = 5 

Без использования индекса каждый запрос занимает приблизительно 2 минуты из-за запроса, требующего сканирования всей базы данных. Я создал индекс таким образом, что мой запрос найдет подмножество данных, содержащих подходящее время, а затем отфильтруется на основе другого значения и, таким образом, я надеюсь, что запрос будет намного быстрее.

Однако запросы, кажется, занимает больше времени, теперь ...

Это странно, потому что в pgAdmin он объясняет, что запрос будет использовать индекс времени и индекс времени сужает данные ~ 800.000 элементов из общего 160 000 000, а затем фильтр по запросу сужает эти данные до 1700 позиций. Это объяснение занимает 17 мс, однако, если я запускаю запрос, он занимает 3 минуты.

Это должно быть быстрее, чем поиск двух критериев соответствия на 160 000 000 предметов!

Я не могу понять, почему это происходит не быстрее, мне интересно, хотя, хотя pgAdmin объясняет запрос, используя индекс времени, он действительно использует его при выполнении запроса?

Есть ли у кого-нибудь идеи или предложения?

Спасибо, Джеймс

UPDATE: Я запустить EXPLAIN ANALYZE на следующей команды:

explain analyze select latitude,longitude from networklogs where value = 5 and time = '2:00' 

Результаты являются:

"Bitmap Heap Scan on networklogs (cost=13178.17..1488620.94 rows=848 width=19) (actual time=3507.923..278760.509 rows=33 loops=1)" 
" Recheck Cond: (time = '2:00'::timestamp without time zone)" 
" Rows Removed by Index Recheck: 38302021" 
" Filter: (value = 5)" 
" Rows Removed by Filter: 882873" 
" -> Bitmap Index Scan on timeindex (cost=0.00..13177.95 rows=530111 width=0) (actual time=695.771..695.771 rows=882906 loops=1)" 
"  Index Cond: (time = '2:00'::timestamp without time zone)" 
"Total runtime: 278764.148 ms" 
+0

Попробуйте ВАКУУМНЫЙ АНАЛИЗ. – randomguy

+0

спасибо, попробовав это сейчас! –

+0

Есть ли у вас какие-либо привилегии для резервного копирования старых данных с определенного момента времени и сохранения только количества последних данных? – bonCodigo

ответ

3

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

CREATE INDEX time_and_value ON networklogs (time, value); 

Используя этот показатель, база данных не будет извлекать данные, чтобы проверить еще одно условие, она будет просто получать данные, которые он знает, уже соответствуют критериям поиска. Заказ, конечно, важен.

Я вижу, что вы используете данные по широте и долготе, возможно, использование типа point было бы хорошо для этого, чтобы вы могли использовать все geometric operators, которые поступают по умолчанию с помощью Postgres.Эти данные также могут быть проиндексированы.

+0

Глядя на вывод EXPLAIN, индекс 'time' соответствует 882 906 строк за 0,7 секунды. Затем база данных забирает еще 27,1 секунды для извлечения всех этих строк (предположительно из-за [большого количества обращений к диску] (http://stackoverflow.com/a/13236089/1026671)), только чтобы отбросить 99,996% из них. Вам определенно нужен индекс для обоих столбцов. – willglynn

+0

Прошу прощения, это 278 секунд (3,16 мс/ряд), а не 27 секунд. Похоже, случайные читают мне. – willglynn

+0

Спасибо за ответы. Ну, поэтому мне нужно будет создать несколько нескольких индексов, возможно ли это? Например, моя фактическая база данных содержит больше столбцов, чем приведенные выше примеры. Мне нужны некоторые индексы, такие как time & value, time & flag, time & noconn ... –

2

PostgreSQL имеет EXPLAIN and EXPLAIN ANALYZE изучить, как запрос выполняется. Вполне вероятно, что PG Admin использует EXPLAIN, чтобы рассказать вам, как будет выполняться запрос; вы можете получить более точные результаты с помощью EXPLAIN ANALYZE, который фактически запускает запрос и производит статистику с фактического запуска. Вы могли бы хотя бы увидеть, где было потрачено время, даже если он использует индексы, как ожидалось.

+0

Спасибо, попробуй! –

+0

Я запустил анализ объяснений, но не могли бы вы объяснить мне, что это значит: «Распаковать битмап-кучу в сетевых журналах (стоимость = 13178.17..1488620.94 rows = 848 width = 19) (фактическое время = 3507.923..278760.509 строк = 33 цикла = 1) «по времени и действию? это первая строка из вывода, кстати ... –

+0

Полный вывод был добавлен в мой первоначальный пост в виде обновления. –

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