Perfmon: Monitorando o Storage


O principal recurso de um banco de dados é o storage, pois é lá onde os dados ficam armazenados. Antigamente o storage eram discos SCSI conectados ao servidor. Hoje os discos ficam escondidos atrás de várias camadas de virtualização:

  • Discos SCSI/SAS/FC estão associados a um Arrays de Disco
  • Arrays de disco ficam conectados a uma Controladora de Disco
  • Controladora de Disco cria uma redundância dos discos (RAID1/5)
  • Controladora de Disco permite criar Discos Lógicos (LUN) sobre as redundâncias de disco
  • Disco Lógico (LUN) é gerenciado pelo Frontend do Storage
  • Disco Lógico (LUN) possui um Cache de Escrita para agilizar escritas pequenas e aleatórias
  • Frontend do Storage estão conectados com os Switches de Fiber Channel
  • Switches de Fiber Channel estão conectados com os Hosts (Servidor) pela HBA
  • Servidor (Hosts) monta as unidades lógicas (LUN) como discos locais
  • Discos locais são gerenciados pelo Partition Manager e Volume Manager
  • Discos locais recebem a formatação NTFS do Windows
  • SQL Server cria os arquivos MDF e LDF nos discos locais

Portanto, o processo de comunicação com o storage pode enfrentar uma série de problemas ao longo do seu caminho. A forma mais fácil de determinar a causa do problema é monitorando com o Performance Monitor.

São apenas 3 etapas:

  1. Calculamos a carga no storage em relação a IOPS
  2. Calculamos a carga no storage em relação a MB
  3. Calculamos o tempo de resposta do storage

Primeiro verificamos a quantidade de IOPS que o servidor está exercendo contra o storage:

  • Disk Reads/sec
  • Disk Writes/sec
  • Disk Transfers/sec (corresponde a Reads + Writes)

Aqui temos um exemplo de um servidor com uma taxa variando de 1000-2000 IOPS. Como referência, um único disco SCSI pode executar aproximadamente 150 IOPS. Portanto, essa carga equivale de 7 a 13 discos SCSI.

image

Em seguida, medimos a a taxa de transferência. Observamos que a taxa fica em torno de 100MB/s. Como referência, uma HBA de 2Gbit consegue transferir aproximadamente 200MB/s.

image

Por fim, medimos o tempo de resposta do storage e verificamos que os tempos ultrapassam 100ms. Adicionalmente podemos comparar com o “outstanding I/O”, que mostra o enfileiramento na HBA. Como referência, o tempo de serviço de um disco SCSI costuma ser de 5ms e discos SSD possuem latência de apenas 0,1ms.

image

Análise: Observamos que o tempo de resposta não é compatível com o tempo de disco usual (5ms). Recomendamos que o storage tenha uma performance de pelo menos 10 discos SCSI dedicados para a LUN.

Servidor com Carga Pesada

Vamos ao segundo exemplo. Dessa vez, vou colocar tudo no mesmo gráfico para analisar a carga:

  • IOPS: variando de 2000 a 6000 com picos chegando a 10000
  • Banda: média de 200MB/s com picos de 400, 1000 e 1600MB/s

image

Comentários: estamos lidando com alta carga contra o storage.

  • 10000 IOPS é praticamente um storage dedicado para o servidor
  • 1000MB/s é suficiente para causar gargalo em HBA de 8Gbit
  • 1000MB/s normalmente requer um Switch FC dedicado

O tempo de resposta: encontra-se abaixo de 10ms com algumas variações próximas a 20ms. Adicionando o enfileiramento de disco, observamos que a fila aumenta rapidamente.

image

Análise: O tempo de resposta do disco está excelente. A carga é extremamente alta (praticamente um storage dedicado) e com tempo de resposta de 10ms. O enfileiramento não deve ser encarado como problema.

Disco de Log de um Servidor com Baixa Carga

Começamos novamente analisando os contadores relacionados a carga IOPS e Transferência (MB/s). Aqui temos uma carga praticamente nula com menos de 50 IOPS e inferior a 10 MB/s. Como referência, podemos usar um disco SCSI realizando 150 IOPS e uma Fiber Channel transmitindo 200  MB/s.

image

No tempo de resposta, vamos analisar somente a latência de escrita. Para isso, ajustamos o gráfico para 0 a 20 milissegundos. Observamos que a latência varia bruscamente entre 2 a 15ms.

image

Análise: Esse disco de log apresenta uma taxa de escrita muito baixa. Entretanto, ele apresenta indícios de que existem gargalos com o storage devido às variações bruscas nos tempos de latência. Se o desempenho estivesse adequado, a latência seria praticamente constante. Embora não haja impacto no sistema atual, esse problema poderá se manifestar quando houver aumento de carga no sistema.

Como esse problema afeta uma LUN com disco de log (escritas pequenas e sequenciais), a carga deveria ser absorvida pelo cache do frontend do storage. Portanto, as variações bruscas de tempo indicam um gargalo no Volume Manager do Windows, Switch FC ou no Frontend do Storage.

Após investigação, determinamos que havia problema no Frontend do Storage (fan-out ratio), ou seja, a porta do frontend estava sobrecarregada com um número muito alto de hosts. A solução foi rebalancear os hosts entre as demais portas do storage.

 

Conclusão

Performance Monitor é a melhor ferramenta para analisar o tempo de resposta do storage, pois permite determinar a carga do sistema (IOPS e MB/s) e medir o tempo de resposta.

Comments (12)

  1. Bruno Fargos disse:

    Olá Fabrício, tudo bem?
    Seu artigo é bem interessante e desperta muitas curiosidades de mensurar ambientes.
    Porém, apenas um leigo fazendo perguntas:
    No artigo você menciona em realizar 3 etapas:
    1) Calculamos a carga no storage em relação a IOPS
    2) Calculamos a carga no storage em relação a MB
    3) Calculamos o tempo de resposta do storage

    E logo em seguida você utiliza o Perfmon para capturar estes valores.
    Seguem minhas dúvidas:
    Do trecho:
    "Primeiro verificamos a quantidade de IOPS que o servidor está exercendo contra o storage:
    Disk Reads/sec
    Disk Writes/sec
    Disk Transfers/sec (corresponde a Reads + Writes)"
    Respectivamente temos:
    1) Calculamos a carga no storage em relação a IOPS --> Disk Reads/sec?
    2) Calculamos a carga no storage em relação a MB --> Disk Writes/sec?
    3) Calculamos o tempo de resposta do storage --> Disk Transfers/sec (corresponde a Reads + Writes)?

    Qual ferramenta usou para quantificar os dados coletados? Podemos observar que as labels dos contadores são diferentes.
    As perguntas são bem iniciantes, mas é que realmente não tenho ainda o conhecimento de como associar estes contadores aos casos.
    Muito obrigado e boa tarde.

    1. Olá Bruno,
      Ótimo comentário! Na verdade, IOPS corresponde a Disk Transfers/sec. Podemos entender que os IOPS tem natureza de leitura ou escrita, que corresponde a Disk Reads e Disk Writes. Se tiver mais perguntas, deixe aqui ou me envie emails.
      Fabricio

  2. Dobereiner M. disse:

    Boa tarde,

    Estou com um problema que se encaixa muito bem ao artigo.
    Após coletar informações de latencia e carga (perfmon --> Partition Manager/Disk Subs system), precisei criar um event trace session para Microsoft-Windows-StorPort.
    Os alertas foram de 0x0f, 0x32 e 0x64 ms. E hovueram momentos que para o comando 88hex que alcancei latencia de 30ms (avg disk sec/transfer) e 26ms no Storport event. :O

    De duas uma: ou balanceamento de hosts, ou, algo muito errado com a solução de meu vendor.

    Resumo, nenhum engenheiro do hardware até agora conseguiu entender o que é para fazer e meu conhecimento morre no debug storport.sys

    Mas é um excelente artigo.

    Parabéns.
    Abs.

    1. Nunca fiz essas coletas detalhadas do StorPort. O que seriam esses hexadecimais (0x0f, 0x32 e 0x64)? São os comandos SCSI ou são os tempos de acesso? Esses tempos parecem "normais"/lentos. Nesse caso específico, poderia ser uma contenção de disco. Mas como esses valores não são exorbitantes, então faria uma aposta: contenção no front-end do storage.
      Qual o problema que vocês estão vendo?
      Abraços, Fabricio

      1. Doereiner M. disse:

        Bom dia Fabrício, tudo bem? Seriam tempos em ms.
        Esta configuração é uma trigger de eventos perfmon para os tempos configurados nos filtros. No meu exemplo eu configurei com 15ms, 50ms e 100ms. A vantagem que ele já nos garante que o problema não está em nossa configuração de SO. Como a base possui mais de 6tb até achei que poderia ser um valor normal, comando de leitura na SCSI, mas percebi esta latência alta em casos de pouco uso.
        Para ter ideia, tenho valores do SQL de stall read para arquivos do BD superiores a 60ms e escrita para os ndfs do tempdb superiores a 150ms.
        Isso falando de uma solução SAN, que distribui os files em todos os spins, e etc..

        1. @Doereiner: Legal, depois voce compartilha mais informações!

          1. Dobereiner M. disse:

            Bom dia Fabrício Catae, tudo bem?

            Infelizmente não consegui um suporte mais avançado para saber exatamente o que acontecia com meu ambiente.
            Para tentar minimizar, realizei algumas ações como transformar todas as tabelas temporárias para table variable (orientando a equipe de dev), apliquei compress nos índices analisando scan vs update e etc.

            Até tivemos ganho e a latência continuou absurda. era sabido, já que mapiei a latência depois da camada storport.sys

            Inclusive, estava analisando o resultado de uma performance de tabelas do tipo variável vs tabelas temporárias e estou tentando entender exatamente o que acontece. O interessante neste ponto é que mesmo sendo uma variável do tipo tabela e o servidor não sofrer nenhuma pressão de memória, uma table variable, cria uma tabela interna temporária física e mesmo assim fica mais rápida. E ela ainda executa read-ahead a mais.

            Fiz um teste em um loop, gerando uma string aleatória com tamanho 5: set @smpTxt = @smpTxt + char(90 - Convert(int,(((1) - 25) * RAND() + 25))) e somei com uma string replicada em 15 caracteres, por 100 mil iterações, dentro de uma table variable.

            Durante a execução do script, identifiquei o id do objeto criado, e analisei com DBCC IND(2, -o_id_do_objeto, 1) e depois

            DBCC PAGE(2, 1, código_de_uma_página_qualquer, 3)

            Pude encontrar meus registros:
            0000000000000000: 30000800 c4cc0000 02000001 0037004d 004c0043 0...ÄÌ.......7.M.L.C
            0000000000000014: 004a0059 00410041 00410041 00410041 00410041 .J.Y.A.A.A.A.A.A.A.A
            0000000000000028: 00410041 00410041 00410041 004100 .A.A.A.A.A.A.A.
            id --> 52420
            name --> MLCJYAAAAAAAAAAAAAAA

            Agora por curiosidade vou tentar descobrir como é possível ainda sim ser mais rápido.

            Feliz 2017.

            {}'s

          2. Ola Dobereiner! Uma variável tabela e tabela temporária são praticamente iguais. São muito parecidas mesmo. Entretanto, se você quiser algo bem diferente, então deveria experimentar a tabela Hekaton com Schema-Only - embora isso normalmente causa uma pressão de memória bastante grande. Abraços, Fabricio

  3. Wolney Marconi Maia disse:

    Olá Fabrício,
    Ótimo post para por em prática e aprender muito!!!
    No primeiro gráfico (Total IOPS) você cita que atingiu taxas entre 1.000 e 2.000 IOPS e pelo que entendi esses valores são as somas de Disk Reads/sec e Disk Writes/sec. Que também pode ser somente o contador Disk Transfers/Sec. Neste caso o objeto do Perfmon utilizado foi o Logical Disk ou o Physical Disk?

    O segundo e terceiro gráficos, não consegui entender como você chegou nos valores.

    No segundo (Total Throughput (Reads/Writes)) você cita que está medindo o tempo de resposta do store e encontra valores próximos a 100MB/s. Mas não identifiquei o contador ou os contadores que chegam nesses valores.

    O mesmo caso se aplica ao terceiro (Disk Response Time) onde se chegou a valores acima de 100ms.

    No casos desses dois gráficos, quais os contadores utilizados?

    Obrigado pela atenção.

    1. Exato. O contador de Disk transfer = disk writes + disk reads.
      Atualmente você pode usar tanto os contadore de Physical Disks ou Logical Disks. Eu normalmente prefiro usar Logical Disks, pois ele fornece descrições melhores sobre o disco. Por exemplo, a representação física pode ser vista como "Disk 0 (LUN 0)" ao invés de "C:". Enfim, faça alguns testes para ver o que você acha. Tem diferenças sim - mas normalmente dá na mesma.

    2. Com relação aos gráficos:
      - Gráfico Total throughput (Reads/Writes): apresenta a unidade de MB/s. É nesse gráfico que dá para ver a média de 100MB/s. Nesse artigo, ele corresponde ao segundo gráfico.
      - Gráfico de Disk Response Time: apresenta unidade de ms. Veja que o gráfico é estranho e extrapola o valor limite de 100ms. Nesse artigo, corresponde ao terceiro gráfico.

Skip to main content