Organizando planos de execução gigantes

7/25/2011 12:16:00 PM By Felipe Pessoto

Neste post quero mostrar uma forma de organizar um plano de execução gigante.

Muitas vezes quando trabalhamos com bancos de dados antigos e complexos, acabamos lidando com problemas de performance e o plano de execução da algumas dicas por onde começar o trabalho de otimização.

O problema é quando o próprio plano de execução é grande e complexo, dificultando a leitura e tornando o simples trabalho de achar os pontos críticos em uma tarefa entediante.

O primeiro passo pra isso é salvar o plano de execução em XML. No Sql Management Studio, basta clicar com o botão direito sobre o Plano de Execução e selecionar "Save Execution Plan As". Após isso é necessário abrir o plano de execução no bloco de notas e re-salvar em Unicode, pois o XML está marcado como Unicode, mas o Management Studio salva em condificação ANSI, o que gera um problema no próximo passo.

Assim que temos o arquivo XML preparado, basta fazer alguns SELECT´s no arquivo XML, onde podemos ordenar por tempo estimado de CPU, IO ou a diferença entre o número de linhas esperados e o número atual:

DECLARE @xml XML

SELECT @xml =(SELECT * FROM OPENROWSET (BULK 'C:\Users\Usuario\Desktop\Exec.txt', SINGLE_BLOB) XMLShowPlan)

SELECT  RelOp.op.value('@NodeId', 'int') AS NodeId,
        RelOp.op.value('@PhysicalOp', 'NVARCHAR(75)') AS Operation,
        RelOp.op.value('@EstimateCPU', 'float') AS EstimatedCPU,
        RelOp.op.value('@EstimateIO', 'float') AS EstimatedIO
FROM    @xml.nodes('declare default element namespace
    "http://schemas.microsoft.com/sqlserver/2004/07/showplan";
    //RelOp') AS RelOp ( op )
ORDER BY [EstimatedCPU] DESC

SELECT  RelOp.op.value('@NodeId', 'int') AS NodeId,
        RelOp.op.value('@PhysicalOp', 'NVARCHAR(75)') AS Operation,
        RelOp.op.value('@EstimateCPU', 'float') AS EstimatedCPU,
        RelOp.op.value('@EstimateIO', 'float') AS EstimatedIO
FROM    @xml.nodes('declare default element namespace
    "http://schemas.microsoft.com/sqlserver/2004/07/showplan";
    //RelOp') AS RelOp ( op )
ORDER BY [EstimatedIO] DESC;

WITH ExPlan AS(

SELECT  RelOp.op.value('@NodeId', 'int') AS NodeId,
        RelOp.op.value('@PhysicalOp', 'NVARCHAR(75)') AS Operation,
        RelOp.op.value('@EstimateCPU', 'float') AS EstimatedCPU,
        RelOp.op.value('@EstimateIO', 'float') AS EstimatedIO,
        RelOp.op.value('@EstimateRows','float') AS EstimatedRows,
        RelOp.op.value('(./*:RunTimeInformation/*:RunTimeCountersPerThread)[1]/@ActualRows','int') AS ActualRows
FROM    @xml.nodes('declare default element namespace
    "http://schemas.microsoft.com/sqlserver/2004/07/showplan";
    //RelOp') AS RelOp ( op )
)

SELECT e.NodeId
 ,e.Operation
 ,e.EstimatedRows
 ,e.ActualRows
 ,(e.EstimatedRows/ActualRows) AS EstActualRatio
  FROM [ExPlan] e
  WHERE e.EstimatedRows > 0
  and e.ActualRows > 0
ORDER BY [EstActualRatio] ASC

Você pode criar outros selects para diversos casos, mas com isso já temos uma base.

Qual a sua opinião sobre programação mais controversa?

5/11/2011 12:04:00 PM By Felipe Pessoto

Uma pergunta feito pelo Jon Skeet, no Stack Overflow, "What's your most controversial programming opinion?".

Há algumas bem interessantes, da até pra fazer uma lista "TODO" para ser um programador melhor.

A mais votada acho que é a mais importante, e tem por consequência a maior parte das outras: "Programmers who don't code in their spare time for fun will never become as good as those that do." Se você programar apenas pra se sustentar vai estar sempre limitado ao que te mandam fazer e dificilmente vai evoluir como quem realmente gosta do que faz, isso vale em qualquer profissão. Se você gosta do que faz, inclusive o faz em seu tempo livre, vai se manter sempre atualizado e aprendendo.

Read more...

Dicas para melhorar a performance no ASP.NET MVC 3

3/5/2011 5:32:00 AM By Felipe Pessoto

Vi o sessão sobre Performance no ASP.NET MVC 3 do mvcConf. Tem algumas dicas para melhorar a performance da aplicação sem grandes alterações:

-Nas View fortemente tipadas sempre passar uma instância do objeto em vez de null. É muito comum na Action Add passar null pra View: "return View();. O problema acontece quando se usa os HtmlHelpers que aceitam Expression Tree, Html.TextBoxFor(x=> x.Name), ele vai disparar uma exception que é automáticamente capturada, mas que impacta na performance.

-Remover View Engines não utilizadas, assim evita que o ASP.NET MVC 3 procure por Views que não existes no disco.

-Usar OutputCache onde possível

-Desisintalar UrlRewriter do IIS caso não esteja usando no servidor

Iterators

1/19/2011 6:16:00 PM By Felipe Pessoto

Muito antigamente, quando se programava em C# 1.0, caso você precisasse implementar as interfaces IEnumerable ou IEnumerator era necessário fazer na mão, implementando os métodos Current, MoveNext e Dispose para o IEnumerator e GetEnumerator para o IEnumerable.
O mais complicado era o MoveNext(), pois é necessário criar uma máquina de estado para saber qual resultado deve ser atribuido ao Current.
Estas interfaces são conceitos importantes no C# e na plataforma .NET em geral, o foreach funciona baseado na classe IEnumerable, chamando seu único método GetEnumerator que por sua vez retorna um object que implementa a interface IEnumerator.

Com o C# 2.0, uma nova keyword e muito trabalho do compilador, é possível simplificar tudo isso. Usando o yield return no seu método ou no get da propriedade o compilador se encarrega de criar uma classe aninhada que implementa essas interfaces pra você, controlando todos os fluxos respeitando if´s, for´s blocos finally, etc. É um trabalho enorme por parte do compilador e claro da equipe do compilador do C# que trabalhou duro no algoritmo. Hoje essa "feature" é uma das maiores no compilador do C#.

Nada melhor do que vermos o código para entender melhor como tudo isto funciona. Vou mostrar um método que retorna IEnumerator<int> e o resultado gerado pelo compilador, usando o Reflector pra isso.

Read more...