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

Como o Access se comunica com fontes de dados ODBC? Parte 2


ATUALIZAÇÃO: Adicionados mais alguns esclarecimentos sobre o significado de SQLExecute e como o Access está lidando com as consultas preparadas. Obrigado, Bob!

O que o Access está fazendo quando navegamos e examinamos registros em uma tabela vinculada ODBC?


Na segunda parte de nossa série de rastreamento ODBC, nosso foco se voltará para o impacto que os tipos de conjunto de registros têm em uma tabela vinculada ao ODBC. No último artigo, aprendemos como ativar o rastreamento ODBC SQL e agora podemos ver a saída. Se você brincou um pouco com isso, deve ter notado que sua consulta do Access e as instruções SQL ODBC que o Access gera não são muito semelhantes. Também forneceremos uma visão detalhada de como os tipos influenciam o comportamento das consultas SELECT e também examinaremos diferentes variações de conjuntos de registros, como Snapshots e Dynasets.

Se você quiser acompanhar, você pode usar o banco de dados de exemplo fornecido aqui.

Efeito dos tipos de Recordset em uma consulta SELECT


Os tipos de conjunto de registros têm um grande efeito sobre como o Access se comunicará com as fontes de dados ODBC. Você deve ter notado que em um modo de exibição de design de formulário ou no modo de exibição de design de consulta, você pode definir o tipo de conjunto de registros. Por padrão, é definido como Dynaset .

No VBA, temos mais poucas opções, mas não vamos nos preocupar com isso por enquanto. Vamos começar entendendo o que exatamente Dynaset e Snapshot significa primeiro. Começaremos com o tipo menos usado, Snapshot primeiro.

Conjuntos de registros do tipo instantâneo


Snapshot é bem simples. Basicamente significa que tiramos um instantâneo do resultado no momento da execução da consulta. Normalmente, isso também significa que o Access não pode atualizar o resultado. No entanto, vamos ver como o Access consulta a fonte com um conjunto de registros baseado em instantâneo. Podemos criar uma nova consulta do Access assim:

O SQL como podemos ver na visualização SQL da consulta do Access é:
SELECT Cities.*
FROM Cities;
Executaremos a consulta e, em seguida, examinaremos o sqlout.txt Arquivo. Aqui está a saída, formatada para facilitar a leitura:
SQLExecDirect:
SELECT
   "CityID"
  ,"CityName"
  ,"StateProvinceID"
  ,"Location"
  ,"LatestRecordedPopulation"
  ,"LastEditedBy"
  ,"ValidFrom"
  ,"ValidTo"
FROM "Application"."Cities"
Houve poucas diferenças entre o que escrevemos na consulta do Access em comparação com o que o Access enviou para o ODBC, que analisaremos.
  1. O acesso qualificou a tabela com o nome do esquema. Obviamente, no dialeto Access SQL, isso não funciona da mesma maneira, mas para o dialeto ODBC SQL, é útil garantir que estamos selecionando da tabela correta. Isso é regido pelo SourceTableName propriedade.
  2. O acesso expandiu o conteúdo de Cities.* em uma lista enumerada de todas as colunas que o Access já conhece com base nos Fields coleção do TableDef subjacente objeto.
  3. O acesso usou o " para citar os identificadores, que é o que o dialeto ODBC SQL espera. Embora o Access SQL e o Transact-SQL usem colchetes para citar um identificador, essa não é uma sintaxe válida no dialeto ODBC SQL.

Portanto, embora tenhamos feito apenas uma consulta de instantâneo simples selecionando todas as colunas de uma tabela, você pode ver que o Access faz muita transformação no SQL entre o que você coloca na exibição de design da consulta do Access ou na exibição SQL versus o que o Access realmente emite para os dados fonte. Nesse caso, no entanto, é principalmente sintático, portanto, não há diferença real na instrução SQL entre a consulta original do Access e a instrução ODBC SQL.

O rastreamento também adicionou SQLExecDirect no início da instrução SQL. Voltaremos a isso depois de analisarmos alguns outros exemplos.

Conjuntos de registros do tipo Dynaset


Usaremos a mesma consulta, mas alteraremos a propriedade de volta ao padrão, Dynaset .
Execute-o novamente e veremos o que obtemos do sqlout.txt . Novamente, está formatado para facilitar a leitura:
SQLExecDirect:
SELECT
  "Application"."Cities"."CityID"
FROM "Application"."Cities"

SQLPrepare:
SELECT
   "CityID"
  ,"CityName"
  ,"StateProvinceID"
  ,"Location"
  ,"LatestRecordedPopulation"
  ,"LastEditedBy"
  ,"ValidFrom"
  ,"ValidTo"
FROM "Application"."Cities"
WHERE "CityID" = ?

SQLExecute: (GOTO BOOKMARK)

SQLPrepare:
SELECT
   "CityID"
  ,"CityName"
  ,"StateProvinceID"
  ,"Location"
  ,"LatestRecordedPopulation"
  ,"LastEditedBy"
  ,"ValidFrom"
  ,"ValidTo"
FROM "Application"."Cities"
WHERE "CityID" = ?
   OR "CityID" = ?
   OR "CityID" = ?
   OR "CityID" = ?
   OR "CityID" = ?
   OR "CityID" = ?
   OR "CityID" = ?
   OR "CityID" = ?
   OR "CityID" = ?
   OR "CityID" = ?

SQLExecute: (MULTI-ROW FETCH)

SQLExecute: (MULTI-ROW FETCH)
Nossa, muita coisa acontecendo! Isso é definitivamente mais chato do que o conjunto de registros do tipo instantâneo. Vamos analisá-los um por um.

O primeiro seleciona apenas o CityID coluna. Essa é a chave primária da tabela, mas mais importante, esse é o índice que o Access está usando em seu lado. Isso se tornará importante quando estudarmos as visões mais tarde. O Access usa essa consulta para obter as chaves e usá-la para preencher outras consultas posteriormente, como veremos.

A segunda instrução está mais próxima da consulta de instantâneo original, exceto que agora temos um novo WHERE filtragem de cláusula no CityID coluna. A partir disso, podemos ver que é uma busca de linha única. Podemos usar as chaves que recebemos da primeira consulta e coletar o restante das colunas dessa consulta. Sempre que essa instrução preparada for executada, você verá um SQLExecute: (GOTO BOOKMARK) .

Mas isso seria ineficiente se tivéssemos que fazer isso para todas as linhas... E é aí que entra a próxima consulta. A 3ª instrução é semelhante à 2ª, mas tem 10 predicados. Esta consulta preparada é executada com cada SQLExecute: (MULTI_ROW FETCH) . Então, o que isso significa é que quando carregamos um formulário ou uma folha de dados ou até mesmo abrimos um conjunto de registros em código VBA, o Access usará a versão de linha única ou a versão de várias linhas e preencherá os parâmetros usando as chaves obtidas no primeiro inquerir.

Busca e ressincronização em segundo plano


Aliás, você já notou como quando você abre um formulário ou uma folha de dados, você não consegue ver o “X de Y” na barra de navegação?

Isso porque o Access não pode saber quantos existem até terminar de coletar os resultados da primeira consulta. É por isso que muitas vezes você pode achar que é muito rápido abrir uma consulta que retorna uma grande quantidade de dados. Você está apenas visualizando apenas uma pequena janela de todo o conjunto de registros enquanto o Access está buscando as linhas em segundo plano. Se você clicar no botão “Go To Last”, poderá descobrir que ele congela o Access. Você teria que esperar até que ele terminasse de buscar todas as chaves na primeira consulta antes de podermos ver o “X de Y” na barra de navegação.

Assim, você pode apreciar como o Access pode fornecer a ilusão de ser rápido para abrir até mesmo um grande conjunto de registros quando usamos um conjunto de registros do tipo dynaset e isso geralmente é uma boa experiência para o usuário.

Finalmente, precisamos observar que temos 3 tipos diferentes de execuções, SQLExecDirect , SQLPrepare e SQLExecute . Você pode ver que com o primeiro não temos nenhum parâmetro. A consulta é simplesmente como está. No entanto, se uma consulta precisar ser parametrizada, ela deve primeiro ser preparada via SQLPrepare e depois executado com SQLExecute com valores para os parâmetros fornecidos. Não podemos ver quais valores foram realmente passados ​​para o SQLExecute declaração embora possamos inferir do que vemos no Access. Você só pode saber se ele buscou uma única linha (usando SQLExecute: (GOTO BOOKMARK) ou várias linhas (usando SQLExecute: (MULTI-ROW FETCH) ). O Access usará a versão de várias linhas para buscar em segundo plano e preencher o conjunto de registros de forma incremental, mas usará a versão de linha única para preencher apenas uma linha. Esse pode ser o caso em um único modo de exibição de formulário em oposição ao formulário contínuo ou modo de folha de dados ou usá-lo para ressincronizar após uma atualização.

Navegando


Com um conjunto de registros grande o suficiente, o Access pode não conseguir terminar de buscar todos os registros. Conforme observado anteriormente, os dados são apresentados ao usuário o mais rápido possível. Normalmente, quando o usuário navega pelo conjunto de registros, o Access continuará buscando mais e mais registros para manter o buffer à frente do usuário.

Mas suponha que o usuário salte para a 100ª linha indo para o controle de navegação e digitando 100 lá?

Nesse caso, o Access enviará as seguintes consultas…
SQLExecute: (MULTI-ROW FETCH)

SQLExecute: (GOTO BOOKMARK)

SQLExecute: (MULTI-ROW FETCH)

SQLExecute: (MULTI-ROW FETCH)
Observe como o Access usa as instruções já preparadas que ele criou no momento da abertura do conjunto de registros. Por já possuir as chaves da primeira consulta, ele consegue saber qual é a linha “100ª”. Para usar um exemplo mais concreto. Suponha que tivéssemos CityID começando em 1, 3, 4, 5…99, 100, 101, 102 sem registro para o CityID = 2 . Na primeira consulta, o CityID 101 estaria na 100ª linha. Portanto, quando o usuário pula para 100, o Access procura a 100ª linha na primeira consulta, veja que é CityID 101, então pega esse valor e o alimenta no SQLExecute: (GOTO BOOKMARK) para navegar imediatamente para esse registro. Em seguida, ele analisa os próximos 10 registros e usa os CityID subsequentes para preencher o buffer com vários SQLExecute: (MULTI-ROW FETCH) . Você deve ter notado que há uma busca de várias linhas antes de uma única busca de linha. O acesso está, na verdade, buscando as linhas 101ª-110ª na busca de várias linhas e busca o 100º registro na próxima busca de linha única.

Depois que o Access obtiver os dados das linhas na 100ª, ele levará o usuário até lá e começará a preencher o buffer em torno dessa 100ª linha. Isso permite que o usuário visualize a 100ª linha sem ter que esperar para carregar todos os registros do 11º ao 99º. O usuário também tem uma experiência de navegação aparentemente rápida quando o usuário clica em anterior ou próximo da nova posição porque o Access já o carregou em segundo plano antes que o usuário o solicitasse. Isso ajuda a dar a ilusão de ser rápido mesmo em uma rede lenta.

Mas mesmo que o usuário deixasse o formulário aberto e ocioso, o Access continuaria a executar a busca em segundo plano e atualizar o buffer para evitar mostrar os dados obsoletos do usuário. Isso é governado pelas configurações de ODBC na caixa de diálogo Opções, na seção Avançado na guia Configuração do cliente:

O padrão para o intervalo de atualização ODBC é de 1500 segundos, mas pode ser alterado. Também pode ser alterado via VBA.

Conclusões:robusto ou tagarela


Agora você deve ver que a principal razão pela qual os conjuntos de registros do tipo dynaset são atualizáveis, mas os conjuntos de registros do tipo instantâneo não são porque o Access é capaz de substituir uma linha no conjunto de registros pela versão mais recente do mesmo do servidor, pois ele sabe como selecionar um fila unica. Por esse motivo, o Access precisa gerenciar 2 consultas ODBC; um para buscar as chaves e outro para buscar o conteúdo real das linhas para uma determinada chave. Essas informações não estavam presentes com um conjunto de registros do tipo instantâneo. Acabamos de receber uma grande bolha de dados.

Analisamos 2 tipos principais de conjuntos de registros, embora existam mais. No entanto, outros são apenas variantes dos 2 tipos que abordamos. Mas, por enquanto, basta lembrar que usar o snapshot é ser robusto em nossa comunicação de rede. Por outro lado, usar dynaset significa que seremos tagarelas. Ambos têm seus altos e baixos.

Por exemplo, o conjunto de registros de instantâneo não precisa de mais comunicação com o servidor depois de recuperar os dados. Desde que o conjunto de registros permaneça aberto, o Access pode navegar livremente pelo cache local. O Access também não precisa manter nenhum bloqueio e, assim, bloquear outros usuários. No entanto, um conjunto de registros de instantâneo é necessariamente mais lento para abrir, pois precisa coletar todos os dados antecipadamente. Pode ser um ajuste ruim para um grande conjunto de registros, mesmo que você pretenda ler todos os dados.

Suponha que você esteja criando um grande relatório do Access com 100 páginas, geralmente vale a pena usar o conjunto de registros do tipo dynaset. Ele pode começar a renderizar a visualização assim que tiver o suficiente para renderizar a primeira página. Isso é melhor do que forçá-lo a esperar até que todos os dados sejam recuperados antes de começar a renderizar a visualização. Embora um conjunto de registros dynaset possa ter bloqueios, geralmente é por um breve período. Só é longo o suficiente para o Access ressincronizar seu cache local.

Mas quando pensamos em quantas solicitações a mais o Access envia pela rede com um conjunto de registros do tipo dynaset, é fácil ver que, se a latência da rede for ruim, o desempenho do Access sofrerá de acordo. Para que o Access permita que os usuários editem e atualizem fontes de dados de maneira genérica, é necessário que o Access acompanhe as chaves para selecionar e modificar uma única linha. Veremos isso nos próximos artigos. No próximo artigo, veremos como a classificação e os grupos afetam um conjunto de registros do tipo dynaset e como o Access determina a chave a ser usada para um conjunto de registros do tipo dynaset.

Para obter mais ajuda com o Microsoft Access, ligue para nossos especialistas no número 773-809-5456 ou envie um email para [email protected].