2015-05-03 3 views
1

Я использовал Influx для хранения данных временных рядов. Это здорово, когда это сработало, а затем примерно через месяц он прекратил работать, и я не мог понять, почему. (Совместимо с этим выпуском https://github.com/influxdb/influxdb/issues/1386)Перемещение от Influx до Postgres, нужны советы

Возможно, Influx будет великолепным в один прекрасный день, но сейчас мне нужно использовать что-то более стабильное. Я думаю о Postgres. Наши данные поступают от многих датчиков, каждый датчик имеет идентификатор датчика. Так что я думаю о структурировании наших данных, как это:

(рк), SensorId (строка), время (временная метка), значение (с плавающей точкой)

Наплыв построен для данных временных рядов, так что, вероятно, имеют некоторые встроенная оптимизация. Нужно ли мне самостоятельно делать оптимизацию, чтобы сделать Postgres эффективным? В частности, у меня есть следующие вопросы:

  1. Influx имеет такое понятие «серия», и это дешево для создания новой серии. Поэтому у меня была отдельная серия для каждого датчика. Должен ли я создать отдельную таблицу Postgres для каждого датчика?

  2. Как настроить индексы для быстрого выполнения запросов? Типичный запрос: выберите все данные для sensor123 за последние 3 дня.

  3. Должен ли я использовать метку времени или целое число для столбца времени?

  4. Как установить политику хранения? Например. удалите данные, которые старше одной недели автоматически.

  5. Будет ли шкала Postgres горизонтально? Могу ли я настроить кластеры ec2 для репликации данных и балансировки нагрузки?

  6. Могу ли я опустить в Postgres? Я читал в некоторых статьях, что я могу использовать date_trunc. Но кажется, что я не могу date_trunc его до определенного интервала, например. 25 секунд.

  7. Любые другие оговорки, которые я пропустил?

Заранее благодарен!

Обновления Хранение столбца времени как целого целого выполняется быстрее, чем сохранение его как метки времени. Я делаю что-то неправильно?

хранить его в качестве временной метки:

postgres=# explain analyze select * from test where sensorid='sensor_0'; 

Bitmap Heap Scan on test (cost=3180.54..42349.98 rows=75352 width=25) (actual time=10.864..19.604 rows=51840 loops=1) 
    Recheck Cond: ((sensorid)::text = 'sensor_0'::text) 
    Heap Blocks: exact=382 
    -> Bitmap Index Scan on sensorindex (cost=0.00..3161.70 rows=75352 width=0) (actual time=10.794..10.794 rows=51840 loops=1) 
     Index Cond: ((sensorid)::text = 'sensor_0'::text) 
Planning time: 0.118 ms 
Execution time: 22.984 ms 

postgres=# explain analyze select * from test where sensorid='sensor_0' and addedtime > to_timestamp(1430939804); 

Bitmap Heap Scan on test (cost=2258.04..43170.41 rows=50486 width=25) (actual time=22.375..27.412 rows=34833 loops=1) 
    Recheck Cond: (((sensorid)::text = 'sensor_0'::text) AND (addedtime > '2015-05-06 15:16:44-04'::timestamp with time zone)) 
    Heap Blocks: exact=257 
    -> Bitmap Index Scan on sensorindex (cost=0.00..2245.42 rows=50486 width=0) (actual time=22.313..22.313 rows=34833 loops=1) 
     Index Cond: (((sensorid)::text = 'sensor_0'::text) AND (addedtime > '2015-05-06 15:16:44-04'::timestamp with time zone)) 
Planning time: 0.362 ms 
Execution time: 29.290 ms 

хранения его в большой целое число:

postgres=# explain analyze select * from test where sensorid='sensor_0'; 


Bitmap Heap Scan on test (cost=3620.92..42810.47 rows=85724 width=25) (actual time=12.450..19.615 rows=51840 loops=1) 
    Recheck Cond: ((sensorid)::text = 'sensor_0'::text) 
    Heap Blocks: exact=382 
    -> Bitmap Index Scan on sensorindex (cost=0.00..3599.49 rows=85724 width=0) (actual time=12.359..12.359 rows=51840 loops=1) 
     Index Cond: ((sensorid)::text = 'sensor_0'::text) 
Planning time: 0.130 ms 
Execution time: 22.331 ms 

postgres=# explain analyze select * from test where sensorid='sensor_0' and addedtime > 1430939804472; 


Bitmap Heap Scan on test (cost=2346.57..43260.12 rows=52489 width=25) (actual time=10.113..14.780 rows=31839 loops=1) 
    Recheck Cond: (((sensorid)::text = 'sensor_0'::text) AND (addedtime > 1430939804472::bigint)) 
    Heap Blocks: exact=235 
    -> Bitmap Index Scan on sensorindex (cost=0.00..2333.45 rows=52489 width=0) (actual time=10.059..10.059 rows=31839 loops=1) 
     Index Cond: (((sensorid)::text = 'sensor_0'::text) AND (addedtime > 1430939804472::bigint)) 
Planning time: 0.154 ms 
Execution time: 16.589 ms 
+1

Ваш вопрос ** слишком широк **, затрагивая несколько вопросов и не следуя инструкциям SO, задающим конкретные вопросы о проблемах программирования, с указанием того, что вы сделали сами. Я бы предложил вам отредактировать это сообщение, чтобы задать что-то конкретное и задать дополнительные вопросы для дополнительных вопросов на соответствующих форумах (например, Q.5 принадлежит dba.stackexchange). – Patrick

+0

16 мс против 29 мс на одном прогоне для каждой версии не является доказательством того, что «* integer быстрее, чем timestamp *». (Небольшая) разница может быть вызвана кэшированием или другими вещами, происходящими в системе (вы должны, например, повторять утверждения, используя 'объяснять (анализировать, verbose, buffers)') –

+0

Я повторил этот оператор несколько раз и целое всегда быстрее чем временная метка. Однако, если я не делаю to_timestamp (1430939804) и вместо этого перекодирую его заранее, это будет так же быстро, как целое. Может быть, to_timestamp называется много раз и не оптимизирован? – user1657624

ответ

0

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

Для запроса, описанных в q2, индекс на столбце recorded_at должен работать (время является SQL зарезервирована ключевым словом, так что лучше избегать, что в качестве имени)

Вы должны использовать TIMESTAMP WITH TIME ZONE в свое время тип данных.

Удержание зависит от вас.

Postgres имеет различные варианты для осколков/репликации. Это большая тема.

Не уверен, что я понимаю вашу цель для # 6, но я уверен, что вы можете что-то понять.

+0

Спасибо, Билл. Вы видите потенциальные проблемы с производительностью, если у меня сотни датчиков, отправляющих данные в Postgres каждые 5 секунд? (Это около 8 миллионов точек каждый день). А что, если мне нужно выбрать одну серию из сотен серий, каждая из которых содержит сотни тысяч очков. Я проведу несколько тестов, но я также ценю ваше мнение. – user1657624

+0

Возможно, вам захочется заглянуть в нечто подобное. http://zaiste.net/2014/07/table_inheritance_and_partitioning_with_postgresql/ Вы можете использовать свое время разбивки. Затем, чтобы удалить старые данные, просто отпустите соответствующие дочерние таблицы. Я думаю, вы обнаружите, что Postgres удивит вас, когда дело доходит до производительности. – Bill

+0

Я проверил тест со 100 датчиками, каждый из которых добавил 50 тыс. Точек, а производительность очень разумная. Единственная часть, которая является медленной, - это объемные вставки точек в db. Я создал индекс на (sensorId, записанный_at), а затем использовал COPY, чтобы вставить точки, и для добавления всех точек потребовалось более 2 минут. Это нормально? Другое дело, что сохранение record_at как большого целого происходит быстрее, чем сохранение его как метки времени. Я обновил исходный вопрос с помощью вывода из psql. – user1657624