Pretendo arquivar mensagens e não tenho certeza de qual devo usar.
Deve ser capaz de conter no máximo 20 bilhões de linhas (é para isso que espero que o número total tenda)
Cada linha terá três colunas: user_id, mensagem, data
O user_id é uma sequência de 30 caracteres. A mensagem tem entre 1 e 20.000 caracteres. Em média, espero que tenha 140 caracteres. (UTF-8, deve permitir emojis, alfabetos diferentes, etc)
Quero apenas um índice para o user_id, não para a mensagem/data.
Eu só pretendo fazer consultas INSERT, e muito simples SELECT * WHERE user_id = XXXXX Haverá muito poucos SELECTs, espero no pico de 10/minuto. Os SELECTs não precisam ser rápidos, qualquer coisa entre 1 e 20 segundos está bom.
Mas haverá muitos INSERTs. Provavelmente cerca de 5.000-10.000 por segundo.
Meu servidor terá: CPU: AMD Ryzen™ 9 7950X3D RAM: 128 GB DDR5 ECC Drives: 1x 7,68 TB NVMe SSD Datacenter (da Hetzner)
Vamos contar 180 bytes por mensagem (incluindo user_id, timestamp e overhead), com 20B de mensagens que equivalem a 3,6 Tb, um pedaço de dados já bastante substancial.
Para evitar E / S aleatória, eu preferiria um banco de dados que pudesse agrupar linhas com as mesmas chaves de índice (neste caso, user_id) juntas no armazenamento. Isso irá acelerar seus SELECTs, e se você ordenar por (user_id,timestamp) enquanto os dados já estão armazenados nessa ordem, nenhuma classificação será necessária.
O Postgresql exigiria um índice extra que duplicaria os dados.
O InnoDB no MySQL/MariaDB agrupa automaticamente com base na chave primária, portanto, se você definir (user_id,timestamp) como PK, essa condição será atendida. O InnoDB também oferece suporte à compactação de páginas com algoritmos modernos como lz4. Se possível, ao inserir um lote de linhas, você deve ordená-las por chave primária . Todo mundo conhece MySQL, então não vou entrar em detalhes.
Outra opção seria Clickhouse . Embora fale SQL, não é exatamente um banco de dados relacional como os habituais. Por exemplo, não faz UPDATEs ou chaves estrangeiras. Destina-se ao OLAP/data warehouse, que é o que você está fazendo. Ele atende a ambas as condições: usando o mecanismo MergeTree , os dados são armazenados automaticamente na ordem especificada para serem agrupados e suportam compactação. É um pouco meticuloso e difícil de configurar. O desempenho geralmente é ridículo se você o usar para o que deveria fazer. Vamos tentar uma consulta muito idiota:
Quanto aos INSERTs, você deve fazer cerca de 1 a 10 por segundo, em massa. Além disso, nunca é uma boa ideia fazer milhares de instruções INSERT por segundo quando você pode fazer apenas uma com todas as linhas agrupadas. A interface python suporta inserções em massa com arrays. Exemplo:
Estatísticas de compressão:
Nesse exemplo simples, obtemos 2,6 milhões de linhas inseridas por segundo com uma taxa de compactação de cerca de 5 neste texto reconhecidamente fácil de compactar. O Python maximizou um núcleo para 37,5s enviando os dados, enquanto o banco de dados usou 21s de tempo de CPU. Basicamente, não estava fazendo muito e o restante dos núcleos estava ocioso.
Qualquer.
A maioria dos sistemas de banco de dados modernos não possui limite de dados por contagem de linhas. O tamanho dos dados em repouso não afeta o desempenho.
Você tem um esquema muito simples e definido. Você também tem casos de uso muito simples. Provavelmente qualquer RDBMS moderno seria uma boa escolha. Se você deseja um com muito suporte e recursos ao usuário e ao mesmo tempo gratuito, o PostgreSQL é uma ótima escolha. Se software pago e de nível empresarial estiver disponível, o SQL Server também é uma excelente escolha. Outras boas opções são MariaDB, Oracle SQL e MySQL.
FWIW, já trabalhei com armazenamento de grandes quantidades de
Message
dados (especificamente mensagens de email) em um RDBMS (SQL Server) no passado. A tabela principal tinha dezenas de bilhões de linhas e estávamos inserindo milhares de linhas por segundo, durante tempos de pico elevados. Consultar pequenas quantidades de dados dessa tabela também foi rápida (menos de um segundo). O hardware por trás do servidor foi muito menos provisionado do que você planeja usar.