Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Este artigo aborda como escrever código PHP rápido contra SQL Server, Base de Dados SQL do Azure, Azure SQL Managed Instance, Azure Synapse Analytics e base de dados SQL em Microsoft Fabric. A orientação aplica-se tanto ao SQLSRV como ao PDO_SQLSRV, que envolvem o mesmo Microsoft ODBC Driver subjacente para SQL Server.
Comece pelas mudanças de maior impacto
Se só conseguir fazer três alterações, faça estas alterações:
- Ativar o agrupamento de ligações. Estabelecer uma nova ligação TLS ao SQL Server demora dezenas a centenas de milissegundos, dependendo do caminho da rede e da negociação do TLS. Reutilizar ligações agrupadas elimina esse custo por pedido. Veja Gerir ligações de forma eficiente.
- Busca apenas as colunas e linhas que precisas.
SELECT *e as consultas ilimitadas são as causas mais comuns de endpoints lentos. Consulte Consulta apenas o que precisa. - Utilize parâmetros com valor de tabela para inserções em massa. Para centenas de linhas ou mais, os parâmetros com valor de tabela (TVPs) são normalmente muito mais rápidos do que as instruções
INSERTlinha a linha e aumentam de forma linear com o número de linhas. Ver Inserir dados de forma eficiente.
Gerir as ligações de forma eficiente
O estabelecimento de ligação é a operação mais dispendiosa que o condutor realiza. Quase todas as investigações de desempenho do PHP terminam com uma correção de gestão de ligações.
Permitir o agrupamento de ligações
A agregação reutiliza ligações ODBC entre pedidos de PHP, em vez de as encerrar no final de cada pedido. O objeto de ligação é descartado quando o seu script termina, mas o handle ODBC subjacente mantém-se ativo no pool do gestor de drivers ODBC e é reutilizado pelo próximo pedido que pede a mesma cadeia de ligação.
Windows: O agrupamento de ligações está ativado por defeito. Para confirmar, deixa essa ConnectionPooling opção fora do teu DSN. Para desativar o agrupamento para fins de depuração, defina ConnectionPooling=0.
Linux e macOS: O pooling de ligações não é uma opção DSN nestas plataformas. Ative-o no gestor de controladores, definindo Pooling=Yes na secção [ODBC] de odbcinst.ini e definindo um valor positivo para CPTimeout na secção do controlador. Por exemplo:
[ODBC]
Pooling=Yes
[ODBC Driver 18 for SQL Server]
Description=Microsoft ODBC Driver 18 for SQL Server
Driver=/opt/microsoft/msodbcsql18/lib64/libmsodbcsql-18.<version>.so.1.1
CPTimeout=120
Encontre o caminho real da biblioteca com odbcinst -q -d -n "ODBC Driver 18 for SQL Server" ou ls /opt/microsoft/msodbcsql18/lib64/. O nome do ficheiro incorpora a versão instalada do driver ODBC e muda com cada lançamento.
CPTimeout (em segundos) controla durante quanto tempo as conexões inativas permanecem no pool antes de serem encerradas. Define-a suficientemente alta para que a maioria dos pedidos encontre uma ligação em pool, mas baixa o suficiente para que as ligações obsoletas a um servidor com falha sejam desativadas razoavelmente depressa. 60 a 300 segundos funcionam bem para a maioria das cargas de trabalho web.
Para mais detalhes, consulte agrupamento de ligações.
Compreenda o custo da primeira consulta
O Multiple Active Result Sets (MARS) está ativado por defeito. Quando o MARS e o pooling de ligações estão ambos ativos, o driver reinicia a ligação em pool na primeira consulta, e esse reset ignora qualquer timeout da consulta que tenha definido para essa primeira consulta. As consultas posteriores na mesma conexão respeitam normalmente o timeout. Se definir tempos limite agressivos para a primeira consulta numa carga de trabalho em pool, tenha esse comportamento em conta ou desative o MARS com MultipleActiveResultSets=false se não precisar dele. Veja a nota sobre MARS e o agrupamento de ligações em Agrupamento de ligações.
Ligações PDO persistentes não são suportadas
PDO_SQLSRV rejeita PDO::ATTR_PERSISTENT. Defini-lo no construtor gera um erro:
SQLSTATE[IMSSP]: An unsupported attribute was designated on the PDO object.
Utilize a agregação de ligações ODBC para reutilização entre pedidos. É o mecanismo nativo do driver, funciona tanto com PDO_SQLSRV como com SQLSRV e encerra ligações inativas em CPTimeout (o que também garante que a renovação dos tokens do Microsoft Entra funcione corretamente).
Reutilizar a ligação dentro de um pedido
Mesmo com pooling, abrir uma nova ligação PDO ou SQLSRV implica um percurso de ida e volta ao ODBC para obter e validar um identificador do conjunto. Abre uma conexão apenas uma vez por pedido e passa-a a todas as funções que dela necessitem.
Sugestão
Um contentor de injeção de dependência ou um acessório preguiçoso é suficiente. O objetivo é evitar new PDO(...) no meio de um gestor de pedidos.
Consulta apenas o que precisas
As idas e vindas na rede e a materialização do conjunto de resultados dominam a latência das consultas na maioria das cargas de trabalho PHP. As correções são as mesmas que se aplicam a todas as camadas de acesso à base de dados.
Selecione apenas as colunas que utiliza
SELECT * Puxa todas as colunas, incluindo varchar(max) e varbinary(max) que eclipsam os dados que realmente consomes. Dê um nome às colunas:
<?php
// Slow: fetches all columns, including a 2 MB LOB column
$stmt = $conn->query("SELECT * FROM dbo.Products");
// Fast: fetches only the two columns the caller uses
$stmt = $conn->query("SELECT ProductID, Name FROM dbo.Products");
Obtém apenas as linhas de que precisas
Envie a filtragem para o SQL Server. Nunca recolhas uma tabela completa no PHP só para filtrar num foreach loop.
<?php
// Slow: transfers every row to PHP, then filters
$rows = $conn->query("SELECT * FROM dbo.Orders")->fetchAll(PDO::FETCH_ASSOC);
$recent = array_filter($rows, fn($r) => $r["OrderDate"] > "2026-01-01");
// Fast: filters on the server
$stmt = $conn->prepare("SELECT OrderID, CustomerID, Total FROM dbo.Orders WHERE OrderDate > ?");
$stmt->execute(["2026-01-01"]);
$recent = $stmt->fetchAll(PDO::FETCH_ASSOC);
Paginar grandes conjuntos de resultados
Para uma vista em lista que mostra algumas centenas de linhas de entre milhões, não devolva todas as linhas nem deixe que o cliente trate disso. Utilize a paginação do lado do servidor com OFFSET ... FETCH:
<?php
function fetchPage(PDO $conn, int $page, int $pageSize): array {
$stmt = $conn->prepare(
"SELECT OrderID, CustomerID, Total
FROM dbo.Orders
ORDER BY OrderID
OFFSET ? ROWS FETCH NEXT ? ROWS ONLY"
);
// With native prepares, execute([...]) binds values as strings.
// OFFSET and FETCH NEXT require integer bindings; bind explicitly.
$stmt->bindValue(1, ($page - 1) * $pageSize, PDO::PARAM_INT);
$stmt->bindValue(2, $pageSize, PDO::PARAM_INT);
$stmt->execute();
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
Escolha o método certo de busca
- Usa
fetch(PDO::FETCH_ASSOC)em loop para iteração em streaming quando não precisas de todas as linhas na memória ao mesmo tempo. -
fetchAll(PDO::FETCH_ASSOC)Use quando o chamador realmente precisa de todo o conjunto (por exemplo, ao renderizar uma resposta JSON completa). - Use
fetchColumn()quando só se preocupa com um único escalar (umCOUNT,SUM, ouMAX). - Use
PDO::FETCH_KEY_PAIRouPDO::FETCH_UNIQUEpara criar dicionários de pesquisa sem uma segunda passagem.
Os modos numéricos de busca (PDO::FETCH_NUM) são marginalmente mais rápidos do que os modos associativos porque saltam a construção do mapa de nomes de coluna. Prefiro clareza; Só muda quando um perfilador sinaliza o overhead de obtenção como significativo.
Prefira SET NOCOUNT ON em procedimentos armazenados e lotes
Cada instrução INSERT, UPDATE e DELETE devolve um token DONE_IN_PROC com o número de linhas afetadas, que o PHP normalmente descarta. O token não adiciona uma viagem de ida e volta, mas cada um ainda custa bytes no fio e uma pequena quantidade de trabalho de driver. Num procedimento com várias instruções ou lote que executa centenas de instruções por chamada, a poupança acumula-se. Desliga-o:
CREATE OR ALTER PROCEDURE dbo.ProcessOrder
@OrderID INT
AS
BEGIN
SET NOCOUNT ON;
UPDATE dbo.Inventory SET Stock = Stock - 1 WHERE ProductID IN (SELECT ProductID FROM dbo.OrderLines WHERE OrderID = @OrderID);
UPDATE dbo.Orders SET Status = 'Processed' WHERE OrderID = @OrderID;
END;
Inserir dados de forma eficiente
Escolha o método de inserção certo consoante o número de linhas que está a mover. A escolha errada pode ser 100 vezes mais lenta.
Menos de cerca de 100 linhas: declaração preparada num ciclo
Para pequenos lotes, execute uma única instrução preparada num ciclo:
<?php
$stmt = $conn->prepare("INSERT INTO dbo.Products (Name, Price) VALUES (?, ?)");
foreach ($products as $p) {
$stmt->execute([$p["name"], $p["price"]]);
}
Envolve o loop numa transação para que todos os inserts sejam comprometidos como uma unidade e o log não tenha de limpar após cada linha:
<?php
$conn->beginTransaction();
try {
$stmt = $conn->prepare("INSERT INTO dbo.Products (Name, Price) VALUES (?, ?)");
foreach ($products as $p) {
$stmt->execute([$p["name"], $p["price"]]);
}
$conn->commit();
} catch (PDOException $e) {
$conn->rollBack();
throw $e;
}
Centenas a milhões de linhas: parâmetros com valores em tabela
Os parâmetros de tabela (TVPs) enviam todo o lote para o SQL Server numa só ida e volta e permitem que o SQL Server processe o conjunto como uma única instrução. Para lotes de centenas de linhas ou mais, os TVPs são normalmente muito mais rápidos do que um ciclo com instruções preparadas e escalam linearmente com o número de linhas.
Primeiro, crie um tipo de tabela no servidor:
CREATE TYPE dbo.ProductTableType AS TABLE (
Name NVARCHAR(100),
Price DECIMAL(10, 2)
);
PDO_SQLSRV passa o TVP como um array associativo cuja chave é o nome do tipo e cujo valor é o conjunto de linhas. Vincule-o com PDO::PARAM_LOB:
<?php
$rows = [];
foreach ($products as $p) {
$rows[] = [$p["name"], $p["price"]];
}
$tvpInput = ["ProductTableType" => $rows];
$stmt = $conn->prepare(
"INSERT INTO dbo.Products (Name, Price) SELECT Name, Price FROM ?"
);
$stmt->bindParam(1, $tvpInput, PDO::PARAM_LOB);
$stmt->execute();
Para um esquema não padrão, passe o esquema como o próximo elemento do array: ["ProductTableType" => $rows, "Sales"]. Para exemplos de sintaxe procedural SQLSRV e procedimentos armazenados, veja Usar parâmetros com valores de tabela.
Milhões de linhas: bcp ou BULK INSERT
Para operações verdadeiramente em massa (cargas de data warehouse, migrações iniciais), use BCP ou BULK INSERT em vez de PHP. Escreve os teus dados num ficheiro delimitado ou de formato nativo, depois executa o bcp ou BULK INSERT a partir de um job agendado, passo ETL ou script de administração.
Caution
Se invocares o bcp a partir do PHP com shell_exec() ou proc_open(), nunca interpolares dados não fidedignos na linha de comandos. Use escapeshellarg() em todos os argumentos, e prefira executar o carregamento fora de banda em vez de num caminho de pedido web.
Reduzir viagens de ida e volta
Cada viagem de ida e volta em rede entre PHP e SQL Server tem um custo fixo. Quando envia cinco extratos num só lote, paga esse custo uma vez em vez de cinco.
Combine declarações relacionadas num único lote
Para operações relacionadas que são executadas em conjunto, coloque as instruções num único lote e processe todos os conjuntos de resultados:
<?php
$sql = "
SELECT * FROM dbo.Customers WHERE CustomerID = ?;
SELECT * FROM dbo.Orders WHERE CustomerID = ?;
SELECT * FROM dbo.Addresses WHERE CustomerID = ?;
";
$stmt = $conn->prepare($sql);
$stmt->execute([$id, $id, $id]);
$customer = $stmt->fetch(PDO::FETCH_ASSOC);
$stmt->nextRowset();
$orders = $stmt->fetchAll(PDO::FETCH_ASSOC);
$stmt->nextRowset();
$addresses = $stmt->fetchAll(PDO::FETCH_ASSOC);
Para SQLSRV, use sqlsrv_next_result para avançar entre conjuntos de resultados.
Ative Múltiplos Conjuntos de Resultados Ativos quando precisar
Múltiplos Conjuntos de Resultados Ativos (MARS) permitem que uma única ligação tenha múltiplas instruções ativas. Sem o MARS, não pode emitir uma nova consulta numa ligação que ainda tenha um conjunto de resultados aberto. Ambos os controladores têm o MARS ativado por defeito. Para o desativar, defina MultipleActiveResultSets=false na sua cadeia de ligação. Ver Desativar Múltiplos Conjuntos de Resultados Ativos (MARS).
O MARS é conveniente, mas não gratuito. Cada conjunto de resultados ativo consome recursos do lado do servidor. Prefira consumir um conjunto de resultados completo antes de começar outro. Usa o MARS para desbloquear padrões de cursor genuinamente aninhados.
Afinar declarações preparadas
As instruções preparadas salvam o driver de voltar a analisar SQL no servidor e permitem-te associar com segurança entradas não confiáveis como parâmetros.
Prefira preparações nativas
PDO_SQLSRV pode preparar instruções em dois modos.
O Native Prepara envia o texto SQL para o servidor uma vez e reutiliza a instrução analisada para cada execução, enviando apenas os valores dos parâmetros em cada execute().
As preparações emuladas mantêm o texto SQL no cliente e reconstroem uma string SQL completa com parâmetros interpolados em cada execução.
Defina PDO::ATTR_EMULATE_PREPARES => false para que o controlador utilize instruções preparadas nativas. As preparações nativas permitem que o SQL Server armazene em cache e reutilize o plano de consulta, e evitam re-analisar o texto SQL em cada execução.
<?php
$conn = new PDO($dsn, null, null, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false,
]);
Reutilizar declarações preparadas
Prepare uma vez, execute muitas vezes. Cada chamada a prepare() implica a alocação de um identificador ODBC e um processamento sintático no servidor. Num ciclo intensivo, mantenha o objeto $stmt ativo e chame execute() dentro do ciclo:
<?php
// Fast: one prepare, many executes.
$stmt = $conn->prepare("UPDATE dbo.Inventory SET Stock = Stock - ? WHERE ProductID = ?");
foreach ($orderLines as $line) {
$stmt->execute([$line["qty"], $line["productId"]]);
}
// Slow: re-prepares the same SQL on every iteration.
foreach ($orderLines as $line) {
$stmt = $conn->prepare("UPDATE dbo.Inventory SET Stock = Stock - ? WHERE ProductID = ?");
$stmt->execute([$line["qty"], $line["productId"]]);
}
Cuidado com TOP (?) e IN (?, ?, ...)
TOPrequer parênteses em torno de um marcador de parâmetro, SELECT TOP (?) ..., para que o SQL Server possa analisar a contagem de linhas como parâmetro.
IN (?, ?, ?, ?) exige um número fixo de marcadores de posição aquando da preparação. Para listas de tamanho dinâmico IN, construa a cadeia de marcadores de posição a partir de um número inteiro validado ou passe a lista como um parâmetro com valor de tabela.
Caution
Nunca interpole a entrada do utilizador em bruto no texto SQL (incluindo o número de marcadores). Lança a contagem com (int) antes de construir a cadeia provisória e passa sempre os valores execute() reais como parâmetros.
Gerir cursores e memória
O tipo de cursor predefinido é PDO::CURSOR_FWDONLY, um cursor apenas de avanço. Transmite linhas para PHP uma de cada vez e não faz buffer, por isso um grande conjunto de resultados é limitado pela memória de buffer de linhas em vez da contagem total de linhas. Normalmente é isso que queres.
Usa cursores com buffer apenas quando precisares de recuar ou contar linhas
PDO::SQLSRV_CURSOR_BUFFERED (um cursor estático com buffer do lado do cliente) carrega antecipadamente todo o conjunto de resultados na memória do PHP. Esta abordagem permite-lhe chamar rowCount(), procurar para trás e reutilizar a afirmação. Por defeito, o buffer está limitado a 10.240 KB (10 MB) através de PDO::SQLSRV_ATTR_CLIENT_BUFFER_MAX_KB_SIZE, e uma consulta cujo conjunto de resultados exceda esse limite devolve false em vez de esgotar a memória do PHP. Podes aumentar o limite até ao limite de memória do PHP, mas ao fazê-lo trocas um false retorno por um erro fatal real Allowed memory size exhausted quando uma consulta ultrapassa o novo limite. Afina deliberadamente.
Ver Tipos de cursor (PDO_SQLSRV).
Os cursores scrolláveis do lado do servidor (PDO::SQLSRV_CURSOR_STATIC, PDO::SQLSRV_CURSOR_DYNAMIC, PDO::SQLSRV_CURSOR_KEYSET) fazem buffer no servidor em vez do cliente, para não consomem memória PHP. No entanto, armazenam recursos do lado do servidor durante toda a duração do cursor e são mais lentos por linha do que apenas para avançar.
Use o modo predefinido apenas de avanço para leituras em streaming. Utilize o armazenamento em buffer no lado do cliente para conjuntos de resultados pequenos quando precisar de rowCount() ou de deslocamento retroativo. Evita cursores scrolláveis do lado do servidor, a menos que estejas a fazer algo específico.
<?php
// Fast, low memory: default forward-only, one row at a time
$stmt = $conn->prepare("SELECT OrderID, Total FROM dbo.Orders");
$stmt->execute();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
// ...
}
// Buffered: only when you need rowCount() or seeking
$stmt = $conn->prepare("SELECT * FROM dbo.SmallLookup", [
PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL,
PDO::SQLSRV_ATTR_CURSOR_SCROLL_TYPE => PDO::SQLSRV_CURSOR_BUFFERED,
]);
$stmt->execute();
$rowCount = $stmt->rowCount();
Para uma explicação completa, veja Tipos de cursor (PDO_SQLSRV) e Tipos de cursor (SQLSRV).
Fluxar valores binários grandes e de caracteres
Para varbinary(max), varchar(max), nvarchar(max), xml e outros tipos grandes, use fluxos PHP em vez de materializar o valor total na memória:
<?php
$stmt = $conn->prepare("SELECT Name, PhotoBlob FROM dbo.Products WHERE ProductID = ?");
$stmt->execute([$id]);
$stmt->bindColumn("PhotoBlob", $photo, PDO::PARAM_LOB);
$stmt->fetch(PDO::FETCH_BOUND);
// $photo is a stream resource; write it directly to disk without loading it all
$outFile = fopen("/tmp/photo.bin", "wb");
stream_copy_to_stream($photo, $outFile);
fclose($outFile);
Para inserir ou atualizar com valores grandes, use SendStreamParamsAtExec=false no SQLSRV para enviar dados de fluxo em blocos após sqlsrv_execute(). Para mais detalhes, veja Enviar dados como fluxo.
Defina os tempos limite apropriados
Os limites de tempo são tanto configurações de desempenho como configurações de fiabilidade. Perguntas longas mantêm ligações à piscina e impedem outros pedidos.
Tempo limite da instrução
Defina um limite de tempo por instrução para que uma consulta descontrolada não retenha uma ligação ao pool indefinidamente. Para PDO_SQLSRV:
<?php
$stmt = $conn->prepare("SELECT ... FROM dbo.HugeTable ...");
$stmt->setAttribute(PDO::SQLSRV_ATTR_QUERY_TIMEOUT, 30); // seconds
$stmt->execute();
Para SQLSRV, passe "QueryTimeout" => 30 no array de opções para sqlsrv_query ou sqlsrv_prepare.
Define um valor que corresponda à tua carga de trabalho. Para um pedido web síncrono, 15 a 30 segundos é o normal. Para uma tarefa em lote em segundo plano, alguns minutos pode ser razoável. Nunca definas o timeout para zero (ilimitado) num pedido web.
Tempo limite de login
LoginTimeout na cadeia de ligação controla quanto tempo o driver espera para estabelecer uma ligação. Defina um valor explícito ao ligar ao Base de Dados SQL do Azure ou ao Azure SQL Managed Instance para que arranques a frio e failovers em grupos de failover não bloqueiem o cliente indefinidamente. Valores entre 30 e 90 segundos funcionam bem para a maioria das cargas de trabalho na cloud. Para detalhes sobre dimensionar LoginTimeout contra ConnectRetryCount * ConnectRetryInterval e os modos de falha resultantes, veja Tempo de Expiração da Ligação. Para a referência de opções, veja Opções de Ligação.
Direcionar cargas de trabalho só de leitura para uma réplica
Para consultas apenas de leitura numa base de dados num grupo de disponibilidade Always On, Azure SQL Managed Instance ou Base de Dados SQL do Azure com escala de leitura ou geo-réplica, adicione ApplicationIntent=ReadOnly à sua cadeia de ligação:
<?php
$dsn = "sqlsrv:Server=<listener>;Database=<database>;" .
"Encrypt=true;ApplicationIntent=ReadOnly";
O encaminhamento apenas de leitura envia a ligação para uma réplica secundária sincronizada, aliviando a carga da réplica primária. Combine com MultiSubnetFailover=true para obter a ligação mais rápida a ouvintes de grupos de disponibilidade multi-sub-net.
Observe o desempenho do servidor
A temporização no lado do cliente só indica quanto tempo uma consulta demorou de ponta a ponta. Para descobrires por que estava lento, usa as ferramentas de diagnóstico incorporadas do SQL Server.
Query Store
A Query Store captura planos de execução, estatísticas de execução e estatísticas de espera para cada consulta na base de dados. Está ativado por predefinição no Base de Dados SQL do Azure, no Azure SQL Managed Instance e na base de dados SQL no Fabric. No SQL Server, ative-o para cada base de dados:
ALTER DATABASE <database_name> SET QUERY_STORE = ON;
Depois, use os relatórios Query Store do SQL Server Management Studio para encontrar as suas consultas mais lentas e frequentemente executadas. Veja Monitorização de desempenho com a Query Store.
SQL do Azure - Informações sobre o desempenho das consultas
Para o Base de Dados SQL do Azure, o Query Performance Insight do portal Azure mostra automaticamente as consultas que mais consomem recursos sem qualquer configuração. Para obter mais informações, veja Query Performance Insight para a Base de Dados SQL do Azure.
SET STATISTICS para uma investigação única
Para uma única consulta que queira perfilar, execute-a no SQL Server Management Studio com estatísticas ativadas:
SET STATISTICS TIME ON;
SET STATISTICS IO ON;
-- your query here
Leituras lógicas altas quase sempre significam um índice em falta ou inutilizável. Tempo de CPU elevado com poucas leituras lógicas geralmente significa um plano de execução inadequado (parameter sniffing, uma conversão implícita que impede a utilização de índices ou uma função escalar que impede o paralelismo).
Eventos Estendidos para rastreamento ao nível do condutor
Para ver exatamente o que o driver envia para o SQL Server (incluindo os valores reais dos parâmetros que interpola), capture uma sessão de Eventos Estendidos usando os rpc_completed eventos e sql_batch_completed .
Performance checklist (Lista de verificação do desempenho)
Use esta lista de verificação como uma revisão pré-implementação de qualquer aplicação PHP que se ligue ao SQL Server:
| Área | Verificar | Reference |
|---|---|---|
| Connection | O agrupamento de ligações está ativado e configurado para a plataforma | Gerir as ligações de forma eficiente |
| Connection | A aplicação reutiliza ligações dentro de um pedido e não abre ligações por consulta | Reutilizar a conexão no âmbito de um pedido |
| Connection |
LoginTimeoutabrange arranques a frio e ativação pós-falha para o SQL do Azure |
Tempo limite de início de sessão |
| Query | As consultas selecionam apenas as colunas necessárias, não SELECT * |
Selecione apenas as colunas que utiliza |
| Query | A filtragem acontece em SQL, não em PHP com array_filter |
Obtenha apenas as linhas de que necessita |
| Query | Grandes conjuntos de resultados são paginados com OFFSET ... FETCH |
Paginar grandes conjuntos de resultados |
| Query | Conjunto de procedimentos armazenados SET NOCOUNT ON |
Prefere SET NOCOUNT ON |
| Inserções | As inserções em lote utilizam parâmetros com valor de tabela, não ciclos por linha | Inserir dados de forma eficiente |
| Statements |
PDO::ATTR_EMULATE_PREPARES está configurado para false |
Prefira preparações nativas |
| Statements | A aplicação reutiliza instruções preparadas entre execuções | Reutilizar declarações preparadas |
| Cursors | A aplicação utiliza o cursor predefinido apenas para frente, a menos que seja necessário buffering | Gerir cursores e memória |
| Memory | Grandes valores binários e de caracteres são transmitidos em streaming, não materializados | Transmitir em fluxo valores binários e de carateres de grande dimensão |
| Interrupções | O tempo limite da instrução está definido em todas as consultas visíveis para o utilizador | Limite de tempo da instrução |
| Roteamento | Cargas de trabalho apenas de leitura definidas ApplicationIntent=ReadOnly onde existe uma réplica |
Encaminhar cargas de trabalho só de leitura |
| Observability | A Query Store está ativada e é revista regularmente | Query Store |
Conteúdo relacionado
- Agregação de Ligações (Microsoft Drivers for PHP for SQL Server)
- Opções de Ligação
- Tipos de Cursor (PDO_SQLSRV Driver)
- Tipos de Cursor (Driver SQLSRV)
- Utilizar parâmetros com valores de tabela (PHP)
- Resolução de Problemas dos Controladores Microsoft para PHP para SQL Server
- Monitorize o desempenho usando o Query Store