Access
 sql >> Base de Dados >  >> RDS >> Access

JetShowPlan:Uma cartilha


Escrevi brevemente sobre o JetShowPlan em meu artigo sobre Tuning Access Query Performance. Como escrevi naquele artigo, SQL é uma linguagem declarativa. Quando você escreve uma consulta, você está dizendo ao mecanismo de banco de dados o que você quer. O mecanismo de banco de dados decide como melhor fazer isso para você. Isso geralmente é bom, porque otimizar operações baseadas em conjuntos é difícil e deixar que o mecanismo de banco de dados faça isso por você permite que você aproveite o conhecimento daqueles que dedicam suas vidas a esse problema específico.

A desvantagem é que o como torna-se uma caixa preta. Você alimenta um pouco de SQL na caixa preta e sai um conjunto de resultados com um monte de dados. O mecanismo de banco de dados é extremamente confiável em fornecer exatamente os dados solicitados. A questão é que o desempenho da recuperação de dados pode estar em todo lugar. Para ser claro, o baixo desempenho quase nunca é culpa do mecanismo de banco de dados. Normalmente, o problema é que estamos perdendo um índice ou filtrando o resultado de uma função VBA ou juntando duas tabelas vinculadas que são armazenadas em locais fisicamente separados.

Quando esse problema surge, precisamos de uma maneira de solucioná-lo. Digite JetShowPlan. Pense nisso como uma chave de fenda especial que nos permite desmontar a caixa preta e espiar dentro para ver como o mecanismo de banco de dados está implementando os comandos SQL que alimentamos. Com esse conhecimento, podemos ajustar o SQL, adicionar um índice ou resolver a origem de nosso gargalo de desempenho.

Vamos começar.

Chave de registro


JetShowPlan funciona escrevendo o plano de consulta (ou seja, o conteúdo da caixa preta) em um arquivo de texto sempre que o mecanismo de banco de dados ACE/Jet executa qualquer inquerir. Este arquivo de texto é preenchido rapidamente. A criação do arquivo de texto requer recursos que prejudicam ainda mais o desempenho da consulta. Assim, só queremos habilitar esse recurso quando estivermos solucionando ativamente um problema.

Como esta é uma ferramenta para usuários avançados, não há configuração na interface do usuário do Access para habilitar este modo. A única maneira de ativá-lo ou desativá-lo é definindo um valor no registro. O valor do registro se ajusta ao seguinte padrão (o texto entre chaves serve como um espaço reservado):
[HKEY_LOCAL_MACHINE\SOFTWARE{\Wow6432Node}\Microsoft\Office\{xx}.0\Access Connectivity Engine\Engines\Debug]
"JETSHOWPLAN"="ON"

Considerações sobre versão e bitness


O padrão de valor do registro que mostrei acima usa algum texto de espaço reservado para explicar as diferenças entre os ambientes do Access. O texto do número da versão \{xx}.0\ deve ser substituído pelo número da versão que corresponde à versão do Access instalada em sua máquina:
  • 12.0 :Acesso 2007
  • 13.0 :pulado para evitar o desencadeamento de triskaidekaphobes
  • 14.0 :Acesso 2010
  • 15.0 :Acesso 2013
  • 16.0 :Acesso 2016 e 2019

O \Wow6432Node ('Wow' significa "Windows de 32 bits no Windows de 64 bits") é necessário apenas se você estiver executando uma versão de 32 bits do Microsoft Access em uma versão de 64 bits do Windows. Se o Access e o Windows forem de 32 bits ou de 64 bits, essa "pasta" (ou "chave" no jargão do registro) será desnecessária.

No formato VBA:
    If Is32BitAccess Xor Is32BitWindows Then
        IncludeWow6432Key = True
    Else
        IncludeWow6432Key = False
    End If

Por exemplo, uma instalação de 32 bits do Access 2010 em execução no Windows de 64 bits exigiria a seguinte entrada de registro:
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Office\14.0\Access Connectivity Engine\Engines\Debug]
"JETSHOWPLAN"="ON"

Da mesma forma, uma instalação de 64 bits do Access 2019 no Windows de 64 bits exigiria:
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\16.0\Access Connectivity Engine\Engines\Debug]
"JETSHOWPLAN"="ON"

Também devo observar que, na primeira vez que você criar essa entrada, provavelmente precisará adicionar a chave "Debug" (pasta) e o nome e os dados do valor JETSHOWPLAN.

Aqui estão os passos para fazer isso:
  1. Execute o regedit como administrador
  2. Navegue até a tecla "\Engines" seguindo as notas acima
  3. Clique com o botão direito do mouse em "\Engines" e escolha Novo -> Chave
  4. Renomeie a chave de "Nova chave nº 1" para "Depurar"

Em seguida, você precisará adicionar o valor da string "JETSHOWPLAN" com o Data "ON " para habilitar a anexação ao showplan.out arquivo ou "DESLIGADO " para parar de anexar ao arquivo.
  1. Clique com o botão direito do mouse na chave "\Debug" e escolha Novo -> Valor da string
  2. Renomeie o valor de "Novo valor nº 1" para "JETSHOWPLAN"
  3. Clique com o botão direito do mouse no nome do valor "JETSHOWPLAN" e escolha Modificar...
  4. Defina os dados do valor como ON em seguida, clique no botão [OK]

Na próxima vez que você iniciar uma nova instância do Access, ela começará a anexar dados ao arquivo Showplan.out. Quaisquer instâncias do Access já em execução quando você fizer as alterações acima não serão afetadas. O mesmo vale para quando você desativa a configuração OFF . As alterações não entram em vigor até que você inicie um novo msaccess.exe instância. Não é necessário fechar as instâncias existentes do Access; é possível ter uma instância aberta do Access que está gravando ativamente no showplan.out enquanto uma instância diferente do Access não está.

Script de atalho automático


Eu não vou mentir; pulando no regedit toda vez que eu quero ativar ou desativar o JetShowPlan é irritante. Se eu tivesse que fazer isso, dificilmente me incomodaria. Mas eu não tenho que fazer isso! Eu criei uma tecla de atalho no Autohotkey que liga e desliga o JetShowPlan.
^#q:: ; Ctl + Win + Q  (feel free to use your own key combination)
    ;--== Toggle JETSHOWPLAN ==--
    
    ;----- BEGIN CONFIGURATION (make all changes here) -------------
    ShowPlanRegView = 64   ; set to 32 for 32-bit Access
    ShowPlanKey = SOFTWARE\Microsoft\Office\16.0\Access Connectivity Engine\Engines\Debug  ; change 16.0 to match Access version
    ;----- END CONFIGURATION ---------------------------------------
    
    SetRegView %ShowPlanRegView%
    RegRead ShowPlanSetting, HKEY_LOCAL_MACHINE\%ShowPlanKey%, JETSHOWPLAN
    If ( ShowPlanSetting = "OFF" ) {
            RegWrite REG_SZ, HKEY_LOCAL_MACHINE\%ShowPlanKey%, JETSHOWPLAN, ON
            If ErrorLevel
                MsgBox Error enabling JetShowPlan. Check permissions on:`n`nHKLM\%ShowPlanKey%`n`nfor user '%A_UserName%'
            Else
                MsgBox JetShowPlan set to ON
    } Else {
            RegWrite REG_SZ, HKEY_LOCAL_MACHINE\%ShowPlanKey%, JETSHOWPLAN, OFF
            If ErrorLevel
                MsgBox Error disabling JetShowPlan. Check permissions on:`n`nHKLM\%ShowPlanKey%`n`nfor user '%A_UserName%'
            Else
                MsgBox JetShowPlan set to OFF
    }
    SetRegView Default
    Return

Agora, quando quero ajustar minhas consultas, pressiono [Ctl] + [Win] + [Q] e vejo uma caixa de mensagem que diz "JetShowPlan definido como LIGADO". Quando termino, fecho o Access, pressiono [Ctl] + [Win] + [Q] e vejo "JetShowPlan definido como OFF".

Ajustando permissões


Tenho duas contas de usuário do Windows diferentes:uma com permissões padrão que uso para o trabalho diário e outra com permissões de administrador para instalar software etc.  Essa é uma prática recomendada de segurança comum.

O problema é que a chave de registro JetShowPlan está na seção HKLM. Por padrão, apenas os administradores podem fazer alterações nos valores nesse hive. Isso é irritante porque quando tento executar meu script Autohotkey, recebo a seguinte mensagem de erro:

Não se preocupe, no entanto. Como a mensagem acima sugere, podemos corrigir isso. A melhor parte é que podemos torná-lo conveniente sem reduzir nossa postura de segurança. Aqui está o truque.
  1. Abra o regedit como administrador
  2. Navegue até o \Debug chave
  3. Clique com o botão direito do mouse em \Depurar key e escolha Permissões...
  4. Clique no botão [Adicionar...]
  5. Digite o nome de usuário na caixa de mensagem acima ('Mike'), clique em [Verificar nomes] e clique em [OK]
  6. Permitir [√] "Controle total" para o usuário
  7. Clique em [OK] para salvar as alterações

Agora quando eu pressiono [Ctl] + [Win] + [Q] ele liga e desliga o JetShowPlan, atualizando o registro automaticamente.

Encontrando Showplan.out


O Access não alertará você sobre onde o mecanismo de banco de dados Jet/ACE está anexando informações do plano de consulta quando o JetShowPlan estiver habilitado. Passei mais tempo do que gostaria de admitir procurando por uma cópia não autorizada de showplan.out . Esta seção irá salvá-lo de compartilhar esse destino.

Local padrão


O primeiro lugar a procurar é na pasta Documentos do usuário atual. Por exemplo, meu nome de usuário do Windows é "Mike", então o primeiro lugar que eu esperaria encontrar o arquivo é:C:\Users\Mike\Documents\showplan.out .

Usando CurDir()


Tecnicamente falando, o showplan.out arquivo é criado no diretório de trabalho atual. Geralmente é a pasta Documentos do usuário atual, mas nem sempre. A maneira infalível de encontrar a localização do arquivo é usar o CurDir() função.

Você pode copiar, colar e executar a seguinte linha de código na janela imediata do VBA IDE para abrir o arquivo showplan.out (supondo que você tenha habilitado o JetShowPlan no registro):
Shell "notepad """ & CurDir & "\showplan.out""", vbNormalFocus

Alterando o local de saída via ChDir()


Se por algum motivo você quiser especificar um local diferente para o showplan.out arquivo, você pode fazer isso usando a função ChDir(). Essa função altera o diretório de trabalho atual. E, como mencionei anteriormente, o diretório atual é onde está o showplan.out arquivo reside. Assim que você alterar o diretório de trabalho atual, o JetShowPlan começará a gravar na nova pasta; não há necessidade de fechar e reabrir o Access.

Por que você pode querer fazer isso? Digamos que você queira comparar três abordagens diferentes para recuperar os mesmos dados. Você escreve três consultas diferentes para ver como as alterações feitas afetam o plano de consulta. Desde showplan.out é tão detalhado, seria bom ter cada plano de consulta em seu próprio arquivo. Isso facilitará a comparação dos planos de consulta. Aqui está como eu poderia fazer isso. O primeiro passo é certificar-se de que cada uma dessas pastas existe. Em seguida, execute as seguintes linhas de código:
ChDir "C:\Users\Mike\Documents\Showplan\A"
DoCmd.OpenQuery "CollectTax1"
ChDir "C:\Users\Mike\Documents\Showplan\B"
DoCmd.OpenQuery "CollectTax2"
ChDir "C:\Users\Mike\Documents\Showplan\C"
DoCmd.OpenQuery "CollectTax3"
ChDir "C:\Users\Mike\Documents"

Use Tudo o que você tem (ou faça o download se você não ainda não tem)


Enquanto CurDir() lhe dará uma localização definitiva para as mudanças mais recentes no showplan.out arquivo, ele não pode dizer quais eram os diretórios de trabalho anteriores. E, se você fechou a instância do Access que criou o showplan.out arquivo, não há garantia de que a próxima instância do Access que você abrir terá o mesmo diretório atual.

Recentemente me deparei com um pequeno utilitário útil chamado "Tudo". É um pequeno executável que indexa todo o seu disco rígido em apenas alguns segundos. Quando a indexação estiver concluída, você poderá pesquisar instantaneamente arquivos ou pastas em qualquer lugar da sua unidade.

Você pode baixar Tudo daqui ou via Chocolatey:choco install everything . Abra Tudo , procure por showplan.out , e em menos de um segundo você verá todas as instâncias do showplan.out em seu computador junto com a data da última modificação. Eu gostaria de ter essa ferramenta anos atrás.

Compreendendo o Showplan.out


A primeira vez que você abre um showplan.out arquivo, espere ficar confuso. Há muito texto e muito disso é ruído. Aqui está um trecho de um arquivo gerado quando abri o banco de dados de exemplo Northwind:

As consultas que começam com um til (~ ) representam SQL bruto que é salvo na folha de propriedades de um formulário ou relatório e não salvo como um objeto QueryDef permanente. Os principais pontos de interesse são as etapas numeradas para cada consulta:01) , 02) , 03) , etc.  Você deseja seguir estas etapas procurando por bons e maus sinais que possam sugerir onde há problemas.

Que eu saiba, não há documentação oficial para a formatação e conteúdo do showplan.out Arquivo. Tudo bem, porém, porque não vamos ficar presos nas minúcias. Nosso principal objetivo é identificar problemas óbvios e resolvê-los. A regra 80/20 se aplica aqui. A maioria dos ganhos de desempenho virá de um ou dois ajustes simples em nossas consultas.

Bons sinais


Isso é tudo sobre índices. Queremos que o plano de consulta use índices, especialmente nas etapas iniciais de uma consulta de várias etapas. Duas palavras-chave diferentes indicam que os índices estão sendo usados:index e rushmore . Rushmore é o codinome da tecnologia de otimização de consultas originalmente desenvolvida pela Fox Software no início dos anos 80. A Microsoft comprou a empresa em 1992 e incorporou a tecnologia no mecanismo de banco de dados Jet.

As consultas que usam a tecnologia Rushmore para processar índices são executadas mais rapidamente do que aquelas que usam índices de maneira mais tradicional. A tecnologia Rushmore só pode ser usada com tabelas do Access (tanto locais quanto vinculadas), juntamente com tabelas vinculadas FoxPro e dBASE. Notavelmente, o Rushmore não pode ser usado com tabelas vinculadas do SQL Server. Para aumentar o desempenho de tabelas vinculadas do SQL Server, geralmente é melhor escrever consultas de passagem, mas isso está além do escopo deste artigo.

Maus sinais


Há alguns maus sinais a serem observados no showplan.out Arquivo. A simples presença desses sinais não significa necessariamente que haja um problema. Dito isso, se você estiver solucionando problemas de uma consulta com baixo desempenho, você pode pensar nessas palavras como sinalizadores de aviso para possíveis problemas:X-Prod , scanning , temp , temporary .

O X-Prod palavra-chave aparece quando você tem uma consulta com uma junção cartesiana (também conhecida como junção cruzada ou produto cruzado). Isso geralmente acontece por engano quando você esquece de unir duas tabelas no editor Query-by-Example (QBE). O resultado é que todos os registros da tabela 1 são comparados com todos os registros da tabela 2.  O número total de registros é o produto das duas contagens da tabela. Portanto, se a tabela 1 tiver 7 registros e a tabela 2 tiver 9 registros, a junção cruzada das duas tabelas retornará 63 registros. Você pode imaginar o problema se ambas as tabelas tiverem milhares de registros ou mais.
01) Inner Join table 'Table1' to table 'Table2'
      using X-Prod join

A próxima palavra-chave a ser observada é digitalização . Se o mecanismo de banco de dados não puder usar um índice para filtrar os resultados, ele retornará à verificação. Isso significa que ele precisa examinar cada linha individualmente para ver se ela atende aos critérios de consulta. Quando você vê esta palavra em um showplan.out geralmente significa que você precisa adicionar um índice à coluna que está sendo verificada. Mas não sempre! Para colunas com baixa cardinalidade (apenas alguns valores exclusivos, como uma coluna de status), geralmente há pouca vantagem em adicionar um índice. Uma vez adicionado, o índice deve ser mantido. Isso diminui as inserções e ocupa espaço em disco. Além disso, se o desempenho da consulta for aceitável nos dados de produção, adicionar um índice à coluna verificada é uma otimização prematura (que você deve evitar).

Finalmente, há o temp e temporário palavras-chave. Isso indica que o mecanismo de banco de dados teve que realizar algum tipo de operação temporariamente. Quando criamos e salvamos um querydef, esse objeto é salvo com certos metadados para otimizar a execução repetida. Obviamente, esses metadados são perdidos quando índices ou junções temporárias saem do escopo. Essas palavras-chave geralmente podem ser ignoradas, mas podem apontar na direção certa se você se deparar com uma consulta de baixo desempenho sem outras falhas mais óbvias.

Para recapitular em termos muito simplificados:
      BOM  >  >  >  >  >  RUIM:
Rushmore> índices> temporário/temporário> varredura> X-Prod

Linguagem personalizada do Notepad++


Se você está lendo meu outro trabalho, sabe que tenho fortes sentimentos sobre o aumento da relação sinal-ruído na programação (e na vida em geral). Para isso, criei um arquivo "linguagem definida pelo usuário" no Notepad++ para adicionar realce de sintaxe ao showplan.out arquivos. Agora, quando abro showplan.out arquivos, eles se parecem com a captura de tela abaixo. As palavras-chave "BOM" são coloridas em texto azul e as palavras-chave "RUIM" são coloridas em texto vermelho. Este é um exemplo de como fazer o código errado parecer errado.

Para configurar isso, siga estas etapas:
  1. Abrir o Bloco de Notas++
  2. Idioma -> Idioma definido pelo usuário -> Defina seu idioma...
  3. Clique em [Criar novo...]
  4. Digite o nome:showplan.out
  5. Clique em [OK]
  6. Vá para _| Pasta e padrão|_ guia
  7. Em "Folding in code 2 style", insira Inputs para entradas Open e End inputs para Fechar
  8. Vá para a guia _|Lista de palavras-chave|_
  9. Clique em [Styler] no 1º grupo e defina a cor do primeiro plano para vermelho
  10. Digite as seguintes palavras-chave "RUIM" no 1º grupo:
    temp temporary scanning X-Prod
  11. Clique em [Styler] no 2º grupo e defina a cor do primeiro plano como azul
  12. Digite as seguintes palavras-chave "GOOD" no 2º grupo:
    rushmore index
  13. Entrar Ext.:saída

Considerações finais


Ao contrário do SQL Server, o mecanismo de banco de dados Jet/ACE não permite que você modifique diretamente os planos de execução de consultas. Isso significa que podemos olhar dentro da caixa preta com o JetShowPlan, mas não podemos religá-lo para fazer o que queremos. Em vez disso, temos que nos concentrar no que podemos controlar:o SQL exato que alimentamos e os índices e relacionamentos entre as tabelas envolvidas.

O uso do JetShowPlan traz benefícios de curto e longo prazo. A curto prazo, o recurso permite corrigir os gargalos em seus aplicativos do Access. A longo prazo, você obtém informações sobre o funcionamento interno do Access, o que ajuda a evitar os gargalos em primeiro lugar.