Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Banco Relacional ou NoSQL para escalar Séries T...

Banco Relacional ou NoSQL para escalar Séries Temporais? Use o PostgreSQL. PgConf.Brasil.2019

Aplicações IoT podem gerar uma imensidão de dados e daí vem a pergunta: Como escalar? O banco de dados relacional é poderoso, porém não é especializado para escalar. Porém, com o PostgreSQL e o TimescaleDB é possível escalar de maneira simples, eficiente e eficaz. O TimescaleDB é uma extensão especializada para dados de séries temporais de código aberto otimizado para consultas rápidas e complexas. Ela fala 'SQL completo' e, de forma correspondente, é fácil de usar como um banco de dados relacional tradicional, além de escalar em formas anteriormente reservadas para bancos de dados NoSQL.

Avatar for eriveltonvichroski

eriveltonvichroski

August 03, 2019
Tweet

Other Decks in Technology

Transcript

  1. Globalcode – Open4education Agenda Motivação Time-series data? TimescaleDB e sua

    Arquitetura TimescaleDB vs PostgreSQL vs NoSQL Usando o TimescaleDB Considerações Finais Dúvidas
  2. Globalcode – Open4education Motivação: IoT IoT - Internet of Things;

    Como processar uma imensidão de dados de maneira escalável sem perder os benefícios do SQL? VLC; Dispositivos de consumo para casas inteligentes; etc. Crédito imagem: https://www.researchgate.net/figure/Outline-of-the-car-positioning-system-with-VLC_fig5_216680068
  3. Globalcode – Open4education Time-series data? Principais características: Centralizado no tempo:

    os dados sempre têm um registro de data e hora; Append-only: os dados são quase exclusivamente anexados (INSERTs); São Recentes: os dados do passado são raramente alterados (Ausência de UPDATEs).
  4. Máquinas industriais Inferências AI & ML Energia Time-series data estão

    presentes em diversas áreas Eventos Web/mobile Transporte & Logistica Financeiro Data Center & DevOps
  5. Exemplo de time-series data Name Tags Data CPU Host=Name,Region=West 1990-01-01

    01:02:00 70 1990-01-01 01:03:00 71 1990-01-01 01:04:00 72 1990-01-01 01:04:00 73 1990-01-01 01:04:00 100
  6. Outro exemplo Name Tags Data CPU Host=Name,Region=West 1990-01-01 01:02:00 70

    1990-01-01 01:03:00 71 1990-01-01 01:04:00 72 1990-01-01 01:04:00 73 1990-01-01 01:04:00 100 FreeMem Host=Name,Region=West 1990-01-01 01:02:00 800M 1990-01-01 01:03:00 600M 1990-01-01 01:04:00 400M 1990-01-01 01:04:00 200M 1990-01-01 01:04:00 0 2 time-series?
  7. Têm estrutura rica Tags Data Host=Name,Region=West 1990-01-01 01:02:00 1990-01-01 01:03:00

    1990-01-01 01:04:00 1990-01-01 01:04:00 1990-01-01 01:04:00 CPU 70 71 72 73 100 MemFree 800M 600M 400M 200M 0 Temp 80 81 82 83 120
  8. Consultas simples select * where time = x Tags Data

    Host=Name,Region=West 1990-01-01 01:02:00 1990-01-01 01:03:00 1990-01-01 01:04:00 1990-01-01 01:04:00 1990-01-01 01:04:00 CPU 70 71 72 73 100 MemFree 800M 600M 400M 200M 0 Temp 80 81 82 83 120
  9. Filtros complexos select * where temp > 100 Tags Data

    Host=Name,Region=West 1990-01-01 01:02:00 1990-01-01 01:03:00 1990-01-01 01:04:00 1990-01-01 01:04:00 1990-01-01 01:04:00 CPU 70 71 72 73 100 MemFree 800M 600M 400M 200M 0 Temp 80 81 82 83 120
  10. Agregações Complexas avg(mem_free) group by (cpu/10) Tags Data Host=Name,Region=West 1990-01-01

    01:02:00 1990-01-01 01:03:00 1990-01-01 01:04:00 1990-01-01 01:04:00 1990-01-01 01:04:00 CPU 70 71 72 73 100 MemFree 800M 600M 400M 200M 0 Temp 80 81 82 83 120
  11. Correlações Como a temp correlaciona-se com a memfree? Tags Data

    Host=Name,Region=West 1990-01-01 01:02:00 1990-01-01 01:03:00 1990-01-01 01:04:00 1990-01-01 01:04:00 1990-01-01 01:04:00 CPU 70 71 72 73 100 MemFree 800M 600M 400M 200M 0 Temp 80 81 82 83 120
  12. Lookup de tags Data 1990-01-01 01:02:00 1990-01-01 01:03:00 1990-01-01 01:04:00

    1990-01-01 01:04:00 1990-01-01 01:04:00 CPU 70 71 72 73 100 Host 1 2 3 4 5 Region 91 91 93 93 95 Region é armazenada na “tabela de tags”
  13. Globalcode – Open4education Time-series data? Com responder as perguntas com

    eficiência? IoT: Como as leituras do sensor de temperatura estão mudando com o tempo? DevOps: Qual é o consumo de memória para cada um dos meus contêineres ontem? Real-Time: Quantos 500 errors cada um dos endpoints da minha API está retornando?
  14. Retenção de Dados + Agregações Granularidade . raw 15 min

    dia Retenção 1 semana 1 mês forever
  15. Globalcode – Open4education TimescaleDB? Banco especializado para Time-series data; Open

    source - Apache 2.0 , TSL e Commercial; Primeira versão em JAN-2017. O que ele “vende”?
  16. Globalcode – Open4education TimescaleDB? Fácil de Usar Interface SQL completa

    (é PostgreSQL) ; Conecta-se a qualquer cliente ou ferramenta que fale com o PostgreSQL; Recursos orientados a tempo, API e otimizações; Políticas robustas de retenção de dados.
  17. Globalcode – Open4education TimescaleDB? Escalável Particionamento de tempo e espaço

    são transparentes (scaling up - single node and scaling out); Elevadas taxas de escrita; Operações paralelizadas; 100 bilhões linhas / nó.
  18. Globalcode – Open4education TimescaleDB? Confiável Projetado a partir do PostgreSQL,

    empacotado como uma extensão; É PostgreSQL; Opções flexíveis de gerenciamento. (compatível com o ecossistema e ferramentas do PostgreSQL).
  19. Globalcode – Open4education TimescaleDB? Confiável Projetado a partir do PostgreSQL,

    empacotado como uma extensão; É PostgreSQL; Opções flexíveis de gerenciamento. (compatível com o ecossistema e ferramentas do PostgreSQL).
  20. Globalcode – Open4education Arquitetura O TimescaleDB é implementado como uma

    extensão no PostgreSQL; Migração do PostgreSQL para o Timescale é simples.
  21. Diversas automatizações • Política da Ordenação • Política de Retenção

    • Política de Tiering • Política de Agregação Contínua
  22. SELECT time, temp FROM data WHERE time > now() -

    interval ‘7 days AND device_id = ‘12345’ Evita querying chunks via exclusão de constraint
  23. Evita querying chunks via exclusão de constraint SELECT time, device_id,

    temp FROM data WHERE time > ‘2017-08-22 18:18:00+00’
  24. Evita querying chunks via exclusão de constraint SELECT time, device_id,

    temp FROM data WHERE time > now() - interval ’24 hours’ Plain PostgreSQL<12 não excluí chunks
  25. Políticas eficientes de retenção de dados SELECT time, device_id, temp

    FROM data WHERE time > now() - interval ’24 hours’ Drop chunks, ao invés de deletar linhas ⇒ Evita vacuuming
  26. Time-series Principalmente UPDATEs Escritas randomicamente distribuídas • Transações para múltiplas

    primary keys Principalmente INSERTs Escritas para o intervalo de tempo recente Escritas associadas com um timestamp e primary key OLTP
  27. Postgres 9.6.2 on Azure standard DS4 v2 (8 cores), SSD

    (premium LRS storage) Each row has 12 columns (1 timestamp, indexed 1 host ID, 10 metrics)
  28. Postgres 9.6.2 on Azure standard DS4 v2 (8 cores), SSD

    (premium LRS storage) Each row has 12 columns (1 timestamp, indexed 1 host ID, 10 metrics)
  29. O custo de manter a B-tree no Insert 1 1

    20 20 10 10 1 1 10 10 13 4 13 4 24 24 29 29 25 25 5 5 Insert batch: 17 17 8 8 Capacidade Memória: 2 NÓS EM MEMÓRIA ESCRITA EM DISCO
  30. O custo de manter a B-tree no Insert 1 1

    20 20 10 10 1 1 10 10 13 4 13 4 24 24 29 29 25 25 5 5 Insert batch: 17 17 8 8 Capacidade memória: 2 NÓS EM MEMÓRIA ESCRITA EM DISCO
  31. 1 1 20 20 10 10 1 1 10 10

    13 4 13 4 24 24 29 29 25 25 Insert batch: 8 8 5 5 17 17 O custo de manter a B-tree no Insert Capacidade memória: 2 NÓS EM MEMÓRIA ESCRITA EM DISCO
  32. 10 10 13 4 13 4 O custo de manter

    a B-tree no Insert 1 1 20 20 10 10 1 1 24 24 29 29 25 25 Insert batch: 8 8 5 5 17 17 Capacidade memória: 2 NÓS EM MEMÓRIA ESCRITA EM DISCO
  33. O desafio de escalar • Índices escrevem de forma randômica

    na B-tree – Examplo: BTREE(device_id, time DESC) • Portanto, em tabelas gigantes teremos: – Índices não cabem na memória – Escritas para locais aleatórios da B-tree – Causa swapping Device: A Time: 01:01:01 Device: Z Time: 01:01:01 Device, Time DESC
  34. Globalcode – Open4education Como o TimescaleBD diz que resolve? Chunk

    = sub-tabela interna; O tamanho do índice ↔ tamanho de cada chunk; As inserções ocorrem nos chunks mas recentes. (cabe na memória e evita acesso ao disco)
  35. Single node: Scaling up via adição de discos • Inserts

    +rápidos • Paralelização de queries Como Benefícios Chunks espalhados em muitos discos (elastically!) com RAID or via tablespaces distintos
  36. Globalcode – Open4education Scaling Out TimescaleDB suporta streaming replication integrada

    ao PostgreSQL; Não é recomendável usar a replicação lógica.
  37. Globalcode – Open4education Scaling Out TimescaleDB suporta streaming replication integrada

    ao PostgreSQL; Não é recomendável usar a replicação lógica.
  38. Simples de começar com a Hipertable CREATE TABLE conditions (

    time timestamptz, temp float, humidity float, device text ); SELECT create_hypertable('conditions', 'time', ‘device', 4, chunk_time_interval => interval '1 week’); INSERT INTO conditions VALUES ('2017-10-03 10:23:54+01', 73.4, 40.7, 'sensor3'); SELECT * FROM conditions; time | temp | humidity | device ------------------------+------+----------+--------- 2017-10-03 11:23:54+02 | 73.4 | 40.7 | sensor3
  39. — Set new chunk time interval SELECT set_chunk_time_interval('conditions', interval '24

    hours’); — Set new number of space partitions SELECT set_number_partitions('conditions', 6); Reparticionamento é simples
  40. PG doesn’t know to use the index Otimização de queries

    CREATE INDEX ON readings(time); SELECT date_trunc(‘minute’, time) as bucket, avg(cpu) FROM readings GROUP BY bucket ORDER BY bucket DESC LIMIT 10; Timescale tem funcões para time
  41. Globalcode – Open4education TimescaleDB x NoSQL NoSQL + LSMTs(Log Structured

    MergeTree) têm seu “custo” para time-series: Consultas complexas são menos poderosas; Ausência de JOINS; Perda do ecossistema SQL.
  42. Armazenamento de valor-chave com pesquisa de chave indexada tem elevadas

    taxas de escritas NoSQL é campeão: Log-Structured Merge Trees + • Compactação de dados • Abordagem comum para time- series: use key <name, tags, field, time>
  43. Log-Structured Merge Tree 5 5 Insert batch: 17 17 8

    8 Memtable 1 3 4 5 7 9 10 1 3 4 5 7 9 10 1 2 3 5 7 9 10 11 1 2 3 5 7 9 10 11 sstables Older
  44. Insert batch: 8 17 5 8 17 5 Memtable 1

    3 4 5 7 9 10 1 3 4 5 7 9 10 1 2 3 5 7 9 10 11 1 2 3 5 7 9 10 11 sstables Older Log-Structured Merge Tree
  45. Log-Structured Merge Tree Insert batch: Memtable 1 3 4 5

    7 9 10 1 3 4 5 7 9 10 1 2 3 5 7 9 10 11 1 2 3 5 7 9 10 11 sstables Older 5 8 17 5 8 17
  46. Problemas com consultas não-KV Se buscar a key 5: Para

    depois de encontrá-lo no primeiro sstable 1 3 4 5 7 9 10 1 3 4 5 7 9 10 1 2 3 5 7 9 10 11 1 2 3 5 7 9 10 11 sstables Dados mais antigos 5 8 17 5 8 17 Se buscar por dados no intervalo de 5-10: É necessário scan em todas sstables Requer estruturas de dados (em memória) para mapear tags para keys Problema de cardinalidade alta ⇒ Prob
  47. Globalcode – Open4education Usando o TimescaleDB Instalação: root@tdc18-timescaledb ~]# sudo

    yum install timescaledb postgresql.conf: shared_preload_libraries = 'timescaledb' [postgres@tdc18-timescaledb data]$ psql -d benchmark psql (10.3) Digite "help" para ajuda. benchmark=#CREATE EXTENSION timescaledb;
  48. Globalcode – Open4education Usando o TimescaleDB Criar uma hypertable: CREATE

    TABLE conditions ( time timestamptz NOT NULL, temp float, humidity float, device text ); SELECT create_hypertable('conditions', 'time', 'device', 4, chunk_time_interval => interval '1 week'); INSERT INTO conditions VALUES ('2017-10-03 10:23:54+01', 73.4, 40.7, 'sensor3'); SELECT * FROM conditions; time | temp | humidity | device -----------------------+------+----------+--------- 2017-10-03 11:23:54+02 | 73.4 | 40.7 | sensor3
  49. Globalcode – Open4education Usando o TimescaleDB Mantenção automática da hypertable:

    teste=# SELECT chunk_id,ranges FROM chunk_relation_size_pretty('conditions'); chunk_id | ranges +---------------------------------------------------------------------------------- 1 | {"['2017-09-27 21:00:00-03','2017-10-04 21:00:00... teste=# INSERT INTO conditions VALUES ('2017-10-11 10:23:54+01', 73.4, 40.7, 'sensor3' teste=# SELECT chunk_id,ranges FROM chunk_relation_size_pretty('conditions'); chunk_id | ranges +---------------------------------------------------------------------------------- 1 | {"['2017-09-27 21:00:00-03','2017-10-04 21:00:00... 2 | {"['2017-10-04 21:00:00-03','2017-10-11 21:00:00...
  50. Globalcode – Open4education Usando o TimescaleDB Explain – Exclusão de

    constraints timescale=# explain SELECT date_trunc('day', pickup_datetime) as day, avg(fare_amount) FROM rides WHERE passenger_count > 1 AND pickup_datetime < '2016-01-08' GROUP BY day ORDER BY day; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ----------------- Finalize GroupAggregate (cost=111571.10..111623.77 rows=200 width=40) Group Key: (date_trunc('day'::text, _hyper_1_6_chunk.pickup_datetime)) -> Gather Merge (cost=111571.10..111617.77 rows=400 width=40) Workers Planned: 2 -> Sort (cost=110571.08..110571.58 rows=200 width=40) Sort Key: (date_trunc('day'::text, _hyper_1_6_chunk.pickup_datetime)) -> Partial HashAggregate (cost=110560.43..110563.43 rows=200 width=40) Group Key: date_trunc('day'::text, _hyper_1_6_chunk.pickup_datetime) -> Result (cost=0.43..109061.13 rows=299860 width=13) -> Parallel Append (cost=0.43..105312.88 rows=299860 width=13) -> Parallel Index Scan using _hyper_1_6_chunk_rides_passenger_count_pickup_datetime_idx on _hyper_1_6_chunk (cost=0.43..35457.47 rows=28315 width=13) Index Cond: ((passenger_count > '1'::numeric) AND (pickup_datetime < '2016-01-08 00:00:00'::timestamp without time zone)) -> Parallel Index Scan using _hyper_1_2_chunk_rides_passenger_count_pickup_datetime_idx on _hyper_1_2_chunk (cost=0.43..29349.27 rows=148788 width=13) Index Cond: ((passenger_count > '1'::numeric) AND (pickup_datetime < '2016-01-08 00:00:00'::timestamp without time zone)) -> Parallel Index Scan using _hyper_1_1_chunk_rides_passenger_count_pickup_datetime_idx on _hyper_1_1_chunk (cost=0.42..20122.63 rows=107501 width=13) Index Cond: ((passenger_count > '1'::numeric) AND (pickup_datetime < '2016-01-08 00:00:00'::timestamp without time zone)) -> Parallel Index Scan using _hyper_1_5_chunk_rides_passenger_count_pickup_datetime_idx on _hyper_1_5_chunk (cost=0.42..18884.21 rows=15256 width=13) Index Cond: ((passenger_count > '1'::numeric) AND (pickup_datetime < '2016-01-08 00:00:00'::timestamp without time zone))