28 de agosto de 2012

Avaliando a performance de queries no SQL Server

Muito da aceitação de um programa de computador por seus usuários pode ser atribuído à praticidade de sua interface gráfica e até mesmo a aparência que ela tenha. No entanto, a aceitação rapidamente se reverte se o programa apresentar problemas de performance. Com bastante frequência, a degradação de performance num programa está associado a queries mal projetadas submetidas a um banco de dados pelo programa.

Quando digo "mal projetada", eu me refiro a certas características das queries adotadas pelo programa, tais como não utilizar os índices apropriados das tabelas ou manter tabelas sem índice, fazer ligações ineficientes com outras tabelas, trazer registros demais que não serão utilizados ou ainda executar uma mesma query mais vezes do que o necessário.

A partir da sua versão 2005, o SQL Server mantém em tabelas virtuais uma série de informações a respeito das queries que foram executadas pelo banco de dados. Essas informações ficam armazenadas em memória e são descartadas quando o serviço do banco é desligado. No entanto, são informações bastante úteis para auxiliar na localização de problemas de performance gerados pelas queries mal planejadas.

Um usuário que queira consultar as informações disponibilizadas nessas tabelas virutais precisa ter atribuida a permissão VIEW SERVER STATE. Isso pode ser feito visualmente, através das propriedades do servidor no Management Studio ou via comando SQL, utilizando-se o GRANT.

Uma das views mais interessantes nesse contexto é a sys.dm_exec_query_stats, responsável pelas estatísticas de execução de queries. Ela traz, dentre outras informações, a quantidade de vezes que uma query foi executada, o tempo gasto nessas execuções, quantas linhas foram retornadas, a quantidade de leituras e gravações feitas durante a execução. Ela dá acesso também ao texto da query e ao plano de execução montado pelo SQL. O exemplo no quadro abaixo lista em ordem decrescente as queries que mais consumiram CPU:
SELECT qs.total_worker_time / qs.execution_count As 'Uso Médio da CPU',
qs.total_worker_time As 'Uso Total da CPU',
qs.execution_count As 'Qtde de Execuções',
qt.text As 'Query',
DB_NAME(qt.dbid) As 'Nome do Banco'
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) As qt
ORDER BY 1 DESC

Veja que a quantidade de vezes que uma query executou não é determinante para que ela tenha consumido mais CPU na média. Consulta semelhante pode ser montada para obter as queries que mais foram executadas (pra avaliar se todas as execuções são mesmo necessárias) ou a quantidade de linhas retornada (pra avaliar se não é possível restringir mais os registros, acrescentando outras comparações à cláusula WHERE). Os tempos listados estão em microsegundos; para convertê-lo em segundos, divida o valor por 1 milhão. É possível ainda levantar a quantidade de gravações feitas por uma query e avaliar se tantas alterações são mesmo necessárias

Outro detalhe a ser destacado no quadro anterior é que o texto da query não está na mesma view. Para obtê-lo, é necessário pegar o código contido no campo sql_handle e repassá-lo à função sys.dm_exec_sql_text.

Outra view bastante útil é a sys.dm_db_missing_index_details. Como o próprio nome diz, ela armazena detalhes sobre o uso de queries cujas execuções não estão otimizadas por que não foi possível encontrar na tabela um índice apropriado. Baseado nas informações retornadas por ela, podemos introduzir novos índices e melhorar a performance das consultas envolvendo as tabelas em questão. O quadro abaixo mostra um exemplo de consulta a essa view, listando as colunas encontradas na cláusula WHERE da query com problema, a tabela envolvida e a quantidade de vezes que a query problemática foi disparada:
SELECT equality_columns, inequality_columns, statement, count(*) As 'Qtde Exec'
FROM sys.dm_db_missing_index_details
WHERE DB_NAME(database_id) = 'ABC71DS94'
GROUP BY equality_columns, inequality_columns, statement
ORDER BY statement

A coluna statement traz o nome da tabela que está sem índice apropriado. A equality_columns lista as colunas usadas em comparações de igualdade no WHERE - algo como NOME_DO_CAMPO = VALOR. Em inequality_columns aparecem as colunas usadas em outros tipos de comparação do WHERE. Veja que é possível filtrar as informações por banco de dados instalado, permitindo avaliar os índices para cada banco isoladamente.

A lista de informações que podemos obter no DMV (Dynamic Management Views) inclui ainda os motivos de espera para uma query ser executada, dados de espelhamento e replicação, tamanho do banco de dados e suas partições, etc. A lista completa das informações disponíveis por esse meio pode ser encontrada em Dynamic Management Views and Functions no MSDN online.

1 de agosto de 2012

Aplicações em Java ainda valem a pena ?

Depois de protagonizar o primeiro grande ataque a sistemas Mac OS no início deste ano, quando uma vulnerabilidade crítica permitiu a infecção de mais de 600 mil Macs, o Java volta a ficar na berlinda. Desta vez, um pesquisador do Centro de Proteção a Malwares da Microsoft publicou um artigo intitulado "Como se proteger de malwares baseados em Java" onde aconselha os usuários a trabalharem sempre com as releases mais recentes da Virtual Machine e, quando for possível, que a deixem desativada para proteger seus sistemas. No caso de não utilizar aplicações Java, a recomendação é de remover completamente o JRE.

Na mesma linha, só que um pouco mais radical, Woody Leonhard defendeu em artigo publicado na InfoWorld.com que a melhor opção é mesmo abandonar a tecnologia, substituindo-a o mais rápido possível. O texto abaixo é uma tradução do artigo onde ele expressa sua opinião:
Quatro meses atrás, eu critiquei o Java -- ou, mais apropriadamente, o uso do Java Runtime Environment (JRE) -- no post "É hora de expulsar o Java da cidade". Quatro meses depois, a situação não melhorou um milímetro. De fato, ela piorou, se é que piorar é uma opção para o vetor de infecção número 1 em PCs e Macs.

Na semana passada, o pesquisador Matt Oh do Centro de Proteção Contra Malware da Microsoft publicou um artigo no TechNet sobre como se proteger contra os malwares baseados em Java. Para enfatizar o ponto, ele deu uma palestra no Black Hat 2012 no mesmo dia, dizendo que a situação com o Java está se deteriorando -- e não somente no Windows.

"Estamos vendo cada vez mais vulnerabilidades no Java sendo exploradas ... e uma vulnerabilidade no Java pode às vezes ser explorada em múltiplas plataformas," disse o pesquisador.

A principal preocupação para Oh são as brechas no sandbox. Se autores de malware conseguirem acesso fora dos limites do sandbox de execução do Java/JRE, eles podem tomar o controle de um sistema, não importando se ele está em Windows, Mac OS X ou Unix. Uma única vulnerabilidade no Java -- como a brecha de segurança "confusão de tipos" CVE-2012-1723, descoberta há apenas algumas semanas, ou a velha CVE-2012-0507, que levou à rede de robôs Flashback, com mais de 600 mil Macs infectados neste ano -- pode resultar numa exploração bem sucedida que burle as defesas do sistema operacional simplesmente por ele estar executando o Java.

"A confusão de tipos é uma vulnerabilidade que ocorre quando a verificação de segurança de tipos feita pelo JRE falha quando são fornecidos tipos diferentes do esperado para uma instrução. Alguns dos tipos do Java, como o ClassLoader, podem ser alvos desse ataque. Se a segurança de tipos dessas classes é quebrada, pode-se ter acesso a alguns métodos que não deveriam estar acessíveis a processos externos à própria classe. Esta violação na segurança de tipos leva, em última análise, ao comprometimento do sandbox do Java," disse Oh.

Para piorar, o fato do programa ser escrito em Java torna mais fácil ocultar a violação usando ferramentas disponíveis e bem documentadas da própria linguagem para embaralhar o código.

A recomendação de Oh é que você esteja sempre com o JRE mais atualizado e que o desabilite sempre que isso for possível. Se você não usa aplicações Java, então simplesmente desinstale o JRE.

Minha recomendação para TI é um pouco mais proativa: é hora de tirar seus usuários da esteira do JRE/JVM. Se você tem um produto que requer o JRE, migre-o. Se seus planos de negócio incluem aplicações Java, altere seus planos. Se você ou sua equipe de desenvolvimento programam aplicações client Java, é hora de diversificar suas habilidades.

Ao continuar usando Java, você está colocando sua empresa e seus clientes em risco.

Embora eu entenda as razões dele e concorde com sua argumentação - que é irretocável, considerando-se a agudez da crise atual - acredito que ainda seja cedo pra tomar uma decisão tal radical quanto simplesmente abdicar das aplicações feitas em Java. Digo isso porque me parece que a Oracle vem mantendo um plano razoavelmente consistente de atualizações da linguagem. Veja, por exemplo, o projeto JigSaw e os planos para levar Java para o iOS.

Apesar de às vezes a Oracle pecar na velocidade das correções, creio que o ideal é seguir as recomendações de Matt Oh: manter sempre atualizado o JRE e eventualmente desligá-lo (se possível) quando brechas críticas forem detectadas e a correção demorar a sair.