Conselhos sobre como dimensionar e melhorar os tempos de execução de uma “consulta à base de pivô” sobre uma mesa bilhões de linhas, o aumento de um milhão por dia

StackOverflow https://stackoverflow.com/questions/1002086

Pergunta

A nossa empresa está desenvolvendo um projeto interno para arquivos de texto de análise. Esses arquivos de texto são compostos de metadados que é extraído usando expresions regulares. Dez computadores estão 24/7 analisar os arquivos de texto e alimentando um high-end Intel Xeon SQL Server 2005 banco de dados com o metadados extraídos.

Os olhares de esquema de banco de dados simplificadas como este:

Items

| Id | Name   |
|----|--------|
| 1  | Sample |
Items_Attributes

| ItemId | AttributeId |
|--------|-------------|
| 1      | 1           |
| 1      | 2           |
Attributes

| Id | AttributeTypeId | Value |
|----|-----------------|-------|
| 1  | 1               | 500mB |
| 2  | 2               | 1.0.0 |
AttributeTypes

| Id | Name    |
|----|---------|
| 1  | Size    |
| 2  | Version |

Há muitos arquivos de texto distintos tipos com interior distinta metadados. Para cada arquivo de texto temos uma Item e para cada valor de metadados extraídos temos um Attribute.

Items_Attributes allow us to avoid duplicate Attribute values which avoids database size to increase x^10.

This particular schema allows us to dynamically add new regular expressions and to obtain new metadata from new processed files no matter which internal structure they have.

Additionally this allow us to filter the data and to obtain dynamic reports based on the user criteria. We are filtering by Attribute and then pivoting the resultset (http://msdn.microsoft.com/en-us/library/ms177410.aspx). So this example pseudo-sql query

SELECT FROM Items WHERE Size = @A AND Version = @B

would return a pivoted table like this

| ItemName | Size  | Version |
|----------|-------|---------|
| Sample   | 500mB | 1.0.0   |

mesa The application has been running for months and performance decreased terribly at the point is no longer usable. Reports should take no more than 2 seconds and Items_Attributes aumenta uma média de 10.000.000 linhas por semana. Tudo está devidamente posicionado e passamos análise e tempo severo otimizar os planos de execução de consulta.

Então, minha pergunta é, como você escalar isso para os tempos de execução de relatórios diminuição?

Nós viemos com este soluções possíveis:

  • comprar mais hardware e configuração de um cluster SQL Server. (Eu preciso de conselhos sobre o bom "agrupamento" estratégia)
  • Use um banco de dados chave / valor como HBase (nós realmente não sei se resolveria nosso problema)
  • Use um ODBMS vez de um RDBMS (que estivemos considerando db4o)
  • Mover nosso software para a nuvem (temos experiência zero)
  • estaticamente gerar relatórios em tempo de execução. (Nós realmente não quer)
  • estática indexados vistas para relatórios comuns (desempenho é quase o mesmo)
  • esquema De-normalize (alguns dos nossos relatórios envolve até 50 mesas em uma única consulta)
Foi útil?

Solução

Talvez este papel branco pela equipe CAT SQL Server nas armadilhas do modelo de banco de dados do atributo de entidade Valor pode ajudar: http://sqlcat.com/whitepapers/archive/2008/09/03/best-practices- para-semântico-modelagem de dados-para-performance-and-scalability.aspx

Outras dicas

Eu começaria de publicar a exata tabelas de metadados (juntamente com detalhes de indexação), texto de consulta exata eo plano de execução.

Com você layout da tabela atual, a consulta semelhante a esta:

SELECT FROM Items WHERE Size = @A AND Version = @B

não pode beneficiar do uso de um índice composto em (Size, Version), já que é impossível construir um índice tal.

Você não pode até mesmo construir uma exibição indexada, uma vez que contém uma auto-associação em attributes.

Provavelmente a melhor decisão seria desnormalizar a tabela como esta:

id  name  size  version

e criar um índice em (size, version)

trabalhou com esquemas muito tempo. Eles nunca um bom desempenho. A melhor coisa é apenas para armazenar os dados que você precisar, no formulário:

| ItemName | tamanho | versão | | ---------- | ------- | --------- | | amostra | 500MB | 1.0.0 |

Em seguida, você don; t necessidade de pivô. E BTW, por favor, não chame seu esquema EAV original "normalizada." - não é normalizada

Parece-me que a emissão de algumas consultas OLAP em um banco de dados otimizado para transações OLTP. Não saber detalhes, eu recomendo a construção de uma "datawarehouse" separado otimizado para o tipo de consultas que você está fazendo. Isso envolveria agregar dados (se possível), desnormalização e também ter uma base de dados, que é de 1 dia de idade ou mais. Você teria incrementalmente atualizar os dados a cada dia ou em qualquer intervalo que você desejar.

Por favor, poste exata DDL e índices, se você tem índices nas colunas ID, em seguida, sua consulta irá resultar em uma varredura

em vez de algo como isto

SELECT FROM Items WHERE Size = @A AND Version = @B

Você precisa fazer isso

SELECT FROM Items WHERE ID = 1

Em outras palavras você precisa pegar os valores de texto, encontrar os ids que você está indexação em e, em seguida, usar isso como sua consulta para retornar resultados em vez

Provavelmente também uma boa idéia de olhar para o particionamento função para distribuir seus dados

agrupamento é feito disponibilidade não o desempenho, se morre um nó (o cluster ativo), o outro nó (o cluster passivo) ficará ativo .... é claro, há também agrupamento ativo ativo, mas isso é outra história

A solução a curto prazo pode ser a utilização horizontal particionamento . Eu estou assumindo que o seu maior tabela é Items_Attributes. Você poderia horizontalmente particionar esta tabela, colocando cada partição em um grupo de arquivos separado em um controlador de disco separado.

Isso supondo que você não está tentando relatório em todos os ItemIds ao mesmo tempo.

Você menciona 50 mesas em uma única consulta. Enquanto servidor SQL suporta até 256 tabelas em uma única consulta, monolítico, esta abordagem reduz as chances do otimizador de produzir um plano eficiente.

Se você está casada com o esquema, tal como está, considere quebrar seu relato consulta em uma série de passos que materializam os seus resultados em tabelas temporárias (#). Esta abordagem permite-lhe realizar o maior número de peças seletivos da consulta isoladamente, e podem, na minha experiência, oferecer grandes ganhos de desempenho. As consultas são geralmente mais fácil de manter também.

Além disso (um pouco de um tiro longo, este) você não diz qual a versão do servidor SQL você está em; mas se você estiver em SQL 2005, dado o número de tabelas envolvidas em seus relatórios e o volume de dados, vale a pena verificar se o seu servidor SQL é remendado a pelo menos SP2.

Eu trabalhei em um projeto de ETL usando tabelas com rowcounts na casa das centenas de milhões, onde encontramos que o otimizador de consulta no SQL 2005 RTM / SP1 não poderia produzir consistentemente planos eficientes para consultas juntar mais de 5 mesas em que um ou mais dos as mesas foi desta escala. Este problema foi resolvido no SP2.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top