Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Este artigo aborda como escrever código PHP rápido contra SQL Server, Banco de Dados SQL do Azure, Instância Gerenciada de SQL do Azure, Azure Synapse Analytics e banco de dados SQL no Microsoft Fabric. A orientação se aplica tanto ao SQLSRV quanto ao PDO_SQLSRV, que envolvem o mesmo Microsoft ODBC Driver subjacente para SQL Server.
Comece pelas mudanças de maior impacto
Se você só puder fazer três mudanças, faça estas alterações:
- Ative o pool de conexões. Estabelecer uma nova conexão TLS com o SQL Server leva dezenas a centenas de milissegundos, dependendo do caminho da rede e da negociação do TLS. Reutilizar conexões agrupadas elimina esse custo por requisição. Veja Gerenciar conexões de forma eficiente.
- Busque apenas as colunas e linhas que você precisa.
SELECT *e consultas sem limites são as causas mais comuns de endpoints lentos. AcesseConsulte apenas o que você precisa. - Use parâmetros com valor de tabela para inserções em lote. Para centenas de linhas ou mais, os parâmetros com valor de tabela (TVPs) geralmente são muito mais rápidos do que as instruções
INSERTlinha por linha e escalam linearmente com o número de linhas. Veja Inserir dados de forma eficiente.
Gerencie conexões de forma eficiente
O estabelecimento de conexão é a operação mais cara que o motorista realiza. Quase toda investigação de desempenho do PHP termina com uma correção de gerenciamento de conexão.
Habilitar o pool de conexões
O pooling reutiliza conexões ODBC entre requisições PHP em vez de desmontá-las no final da requisição. O objeto de conexão é descartado quando seu script termina, mas o handle ODBC subjacente permanece ativo no pool do gerenciador de drivers ODBC e é reutilizado pela próxima solicitação que pede a mesma cadeia de conexão.
Windows: O pooling de conexões está ativado por padrão. Para confirmar, deixe essa ConnectionPooling opção fora do seu DSN. Para desativar o pool para depuração, defina ConnectionPooling=0.
Linux e macOS: O pooling de conexões não é uma opção DSN nessas plataformas. Ative-o no gerenciador de drivers definindo Pooling=Yes na [ODBC] seção de odbcinst.ini e defina um CPTimeout positivo na seção do driver. 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 arquivo incorpora a versão instalada do driver ODBC e muda a cada lançamento.
CPTimeout (em segundos) controla quanto tempo as conexões ociosas ficam na piscina antes de serem fechadas. Defina um valor suficientemente alto para que a maioria das solicitações encontre uma conexão em pool, mas suficientemente baixo para que conexões obsoletas com um servidor em failover sejam encerradas rapidamente. 60 a 300 segundos funcionam bem para a maioria das cargas de trabalho web.
Para mais detalhes, consulte pool de conexões.
Entenda o custo da primeira consulta
O MARS (conjunto de resultados ativos múltiplos) está habilitado por padrão. Quando MARS e o pool de conexões estão ativos, o driver redefine a conexão do pool na primeira consulta, e essa redefinição ignora qualquer tempo limite da consulta que você definiu para essa primeira consulta. Consultas posteriores na mesma conexão respeitam normalmente o timeout. Se você definir tempos limite agressivos para a primeira consulta em uma carga de trabalho em pool, leve em consideração esse comportamento ou desative o MARS com MultipleActiveResultSets=false se não precisar dele. Consulte a nota sobre MARS e pool em Pool de conexões.
Conexões PDO persistentes não são suportadas
PDO_SQLSRV rejeita PDO::ATTR_PERSISTENT. Definir isso no construtor gera uma exceção:
SQLSTATE[IMSSP]: An unsupported attribute was designated on the PDO object.
Use o pool de conexões ODBC para reutilização entre requisições. É o mecanismo nativo do driver, funciona tanto para PDO_SQLSRV quanto para SQLSRV e encerra conexões ociosas em CPTimeout (o que também mantém a atualização do token Microsoft Entra correta).
Reutilize a conexão dentro de uma solicitação
Mesmo com o pool, abrir uma nova conexão PDO ou SQLSRV incorre em uma viagem de ida e volta ODBC para buscar e validar um identificador em pool. Abra uma conexão uma vez por requisição e passe-a para todas as funções que precisem dela.
Dica
Um contêiner de injeção de dependência ou um acessador preguiçoso é suficiente. O objetivo é evitar new PDO(...) no meio de um gerenciador de requisições.
Consulte apenas o que você precisa
As idas e voltas pela rede e a materialização de conjuntos de resultados dominam a latência das consultas na maioria das cargas de trabalho em PHP. As correções são as mesmas que se aplicam a todas as camadas de acesso a banco de dados.
Selecione apenas as colunas que você usa
SELECT * Retorna todas as colunas, incluindo colunas varchar(max) e varbinary(max) que superam em muito os dados que você realmente consome. Nomeie as 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");
Busque apenas as fileiras que você precisa
Envie a filtragem para o SQL Server. Nunca carregue a tabela inteira no PHP só para filtrá-la em um loop foreach.
<?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 lista que mostra algumas centenas de linhas entre milhões, não retorne todas as linhas e deixe o cliente processá-las. Use paginação no 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
- Use
fetch(PDO::FETCH_ASSOC)em um loop para iteração de fluxo quando você não precisa de todas as linhas na memória ao mesmo tempo. -
fetchAll(PDO::FETCH_ASSOC)Use quando o chamador realmente precisar de todo o conjunto (por exemplo, renderizando uma resposta JSON completa). - Use
fetchColumn()quando você só se importa com um único escalar (umCOUNT,SUM, ouMAX). - Use
PDO::FETCH_KEY_PAIRouPDO::FETCH_UNIQUEpara criar dicionários de busca sem uma segunda passada.
Modos numéricos de busca (PDO::FETCH_NUM) são marginalmente mais rápidos que modos associativos porque pulam a construção do mapa de nomes de coluna. Prefira clareza; troque apenas quando um profiler sinalizar sobrecarga de busca como significativa.
Prefira SET NOCOUNT ON em procedimentos armazenados e lotes
Cada instrução INSERT, UPDATE e DELETE retorna 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 na rede e uma pequena quantidade de trabalho do driver. Em um procedimento ou lote com várias instruções que executa centenas de instruções por chamada, a economia se acumula. Desligue:
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 certo de inserção com base em quantas fileiras você está movendo. A escolha errada pode ser 100 vezes mais lenta.
Menos de cerca de 100 linhas: declaração preparada em um loop
Para pequenos lotes, execute uma única instrução preparada em um loop:
<?php
$stmt = $conn->prepare("INSERT INTO dbo.Products (Name, Price) VALUES (?, ?)");
foreach ($products as $p) {
$stmt->execute([$p["name"], $p["price"]]);
}
Envolva o loop em uma transação para que todas as inserções sejam confirmadas como uma unidade e o log não precise ser liberado 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 de tabela
Parâmetros de tabela (TVPs) enviam todo o lote para o SQL Server em uma única 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 tipicamente muito mais rápidos que um loop de declaração preparada e escalam linearmente com a contagem 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 de valores de tabela.
Milhões de linhas: bcp ou BULK INSERT
Para operações realmente em massa (cargas de data warehouse, migrações iniciais), use BCP ou BULK INSERT em vez de PHP. Escreva seus dados em um arquivo delimitado ou de formato nativo, depois execute o bcp ou BULK INSERT a partir de um job agendado, etapa ETL ou script de administração.
Caution
Se você chamar o bcp a partir de PHP com shell_exec() ou proc_open(), nunca interpole dados não confiáveis na linha de comando. Use escapeshellarg() em todos os argumentos, e prefira executar a carga fora de banda em vez de em um caminho de requisição web.
Reduzir viagens de ida e volta
Cada ida e volta de rede entre PHP e SQL Server tem um custo fixo. Quando você envia cinco extratos em um lote, paga esse custo uma vez em vez de cinco vezes.
Combine instruções relacionadas em um único lote
Para trabalhos relacionados que são executados juntos, coloque as instruções em um lote e consuma 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 conexão tenha múltiplas instruções ativas. Sem o MARS, você não pode emitir uma nova consulta em uma conexão que ainda tem um conjunto de resultados aberto. Ambos os drivers ativam o MARS por padrão. Para desativá-lo, defina MultipleActiveResultSets=false na sua cadeia de conexão. Veja Desabilitar 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 completamente antes de iniciar outro. Use MARS para desbloquear padrões de cursor genuinamente aninhados.
Ajuste declarações preparadas
Instruções preparadas evitam que o driver precise analisar novamente o SQL no servidor e permitem associar com segurança dados de entrada não confiáveis como parâmetros.
Prefira preparações nativas
PDO_SQLSRV pode preparar instruções em dois modos.
Preparações nativas enviam o texto SQL para o servidor uma única vez e reutilizam a instrução analisada para cada execução, enviando apenas os valores dos parâmetros em cada execute().
Preparações emuladas mantêm o texto SQL no cliente e reconstroem uma string SQL completa com os parâmetros interpolados em cada execução.
Configure PDO::ATTR_EMULATE_PREPARES => false para que o driver use preparações nativas. 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 várias vezes. Cada chamada prepare() custa uma alocação de identificador ODBC e uma análise no servidor. Em um loop ativo, mantenha o objeto $stmt ativo e chame execute() dentro do loop:
<?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 ao redor de um marcador de parâmetro, SELECT TOP (?) ..., para que o SQL Server possa analisar a contagem de linhas como um parâmetro.
IN (?, ?, ?, ?) exige um número fixo de placeholders no momento da preparação. Para tamanhos de lista dinâmicos IN construa a string de espaço reservado a partir de uma contagem inteira validada ou passe a lista como um parâmetro com valor de tabela.
Caution
Nunca interpole a entrada bruta do usuário no texto SQL (incluindo a contagem de espaço reservado). Converta a contagem com (int) antes de construir a string de espaço reservado e sempre passe os valores reais por meio de execute() como parâmetros.
Gerencie cursores e memória
O tipo de cursor padrão é PDO::CURSOR_FWDONLY, um firehose somente para frente. Ele transmite linhas para o PHP uma de cada vez e não armazena em buffer, portanto, um grande conjunto de resultados é limitado pela memória do buffer de linhas em vez da contagem total de linhas. Geralmente é isso que você quer.
Use cursores com buffer apenas quando precisar recuar ou contar linhas
PDO::SQLSRV_CURSOR_BUFFERED (um cursor estático armazenado em buffer no lado do cliente) carrega todo o conjunto de resultados na memória do PHP antecipadamente. Essa abordagem permite que você chame rowCount(), busque para trás e reutilize a instrução. Por padrão, o buffer é limitado a 10.240 KB (10 MB) por meio de PDO::SQLSRV_ATTR_CLIENT_BUFFER_MAX_KB_SIZE, e uma consulta cujo conjunto de resultados excede esse limite retorna false em vez de causar estouro da memória do PHP. Você pode elevar o limite até o limite de memória do PHP, mas, ao fazer isso, você troca um retorno false por um erro fatal Allowed memory size exhausted real quando uma consulta excede o novo limite. Ajuste cuidadosamente.
Veja Tipos de cursor (PDO_SQLSRV).
Os cursores roláveis do lado do servidor (PDO::SQLSRV_CURSOR_STATIC, PDO::SQLSRV_CURSOR_DYNAMIC, PDO::SQLSRV_CURSOR_KEYSET) armazenam em buffer no servidor em vez do cliente, portanto, não consomem memória do PHP. No entanto, eles mantêm recursos do lado do servidor durante a duração do cursor e são mais lentos por linha do que os somente para frente.
Use o somente para frente padrão para leituras de streaming. Use buffer no lado do cliente para conjuntos de resultados pequenos quando precisar de rowCount() ou rolagem para trás. Evite cursores roláveis do lado do servidor, a menos que você esteja fazendo 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 análise 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 inteiro 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 detalhes, veja Enviar dados como um fluxo.
Definir tempos limite apropriados
Os tempos limite são configurações de desempenho tanto quanto configurações de confiabilidade. Consultas de longa duração mantêm conexões do pool e prejudicam outras solicitações.
Tempo limite da instrução
Defina um limite de tempo por instrução para que uma consulta descontrolada não mantenha uma conexão do 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.
Defina um valor que combine com sua carga de trabalho. Para uma requisição web síncrona, de 15 a 30 segundos é o normal. Para um trabalho em lote em segundo plano, vários minutos podem ser razoáveis. Nunca defina o timeout para zero (ilimitado) em uma requisição web.
Tempo limite do logon
LoginTimeout na string de conexão controla por quanto tempo o driver espera para estabelecer uma conexão. Defina um valor explícito ao conectar-se ao Banco de Dados SQL do Azure ou à Instância Gerenciada do SQL do Azure para que inicializações a frio e failovers de grupo de failover não travem o cliente indefinidamente. Valores de 30 a 90 segundos funcionam bem para a maioria das cargas de trabalho em nuvem. Para detalhes sobre dimensionamento LoginTimeout contra ConnectRetryCount * ConnectRetryInterval e os modos de falha resultantes, veja Tempo de espera da conexão. Para a referência de opções, veja Opções de conexão.
Encaminhar cargas de trabalho somente leitura para uma réplica
Para consultas somente leitura em um banco de dados em um grupo de disponibilidade Always On, Instância Gerenciada do SQL do Azure ou Banco de Dados SQL do Azure com escalonamento horizontal de leitura ou réplica geográfica, adicione ApplicationIntent=ReadOnly à sua cadeia de conexão:
<?php
$dsn = "sqlsrv:Server=<listener>;Database=<database>;" .
"Encrypt=true;ApplicationIntent=ReadOnly";
O roteamento somente leitura envia a conexão para uma réplica secundária sincronizada, descarregando o trabalho da primária. Combine com MultiSubnetFailover=true para obter a conexão mais rápida com ouvintes de grupos de disponibilidade de várias sub-redes.
Observe o desempenho do servidor
O tempo de execução no lado do cliente informa apenas quanto tempo uma consulta levou para ser executada de ponta a ponta. Para descobrir por que estava lento, use os diagnósticos integrados do SQL Server.
Repositório de Consultas
A Repositório de Consultas captura planos de execução, estatísticas de execução e estatísticas de espera para cada consulta no banco de dados. Ele está ativado por padrão no Banco de Dados SQL do Azure, Instância Gerenciada de SQL do Azure e SQL Database no Fabric. No SQL Server, ative-o por banco de dados:
ALTER DATABASE <database_name> SET QUERY_STORE = ON;
Depois, use os relatórios Repositório de Consultas do SQL Server Management Studio para encontrar suas consultas mais lentas e frequentemente executadas. Veja Monitorando o desempenho com a Repositório de Consultas.
Análise de Desempenho de Consultas do SQL do Azure
Para o Banco 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, confira Análise de Desempenho de Consultas para o Banco de Dados SQL do Azure.
SET STATISTICS para investigação única
Para uma única consulta que você deseja 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 ausente ou inutilizável. Um tempo de CPU elevado com poucas leituras lógicas geralmente indica um plano ruim (detecção de parâmetros, uma conversão implícita que impede o uso de índices ou uma função escalar que impede o paralelismo).
Eventos estendidos para rastreamento em nível de driver
Para ver exatamente o que o driver envia para o SQL Server (incluindo os valores reais dos parâmetros que ele interpola), capture uma sessão de Eventos Estendidos usando os eventos rpc_completed e sql_batch_completed.
Lista de verificação de desempenho
Use esta lista de verificação como uma revisão pré-implantação de qualquer aplicativo PHP que se conecte ao SQL Server:
| Area | Verificação | Reference |
|---|---|---|
| Connection | O pool de conexões está habilitado e configurado para a plataforma | Gerencie conexões de forma eficiente |
| Connection | O aplicativo reutiliza conexões dentro de uma requisição e não abre conexões por consulta | Reutilize a conexão dentro de uma solicitação |
| Connection |
LoginTimeout abrange inicializações a frio e failover para o SQL do Azure |
Tempo de encerramento do login |
| Consulta | As consultas selecionam apenas as colunas necessárias, não SELECT * |
Selecione apenas as colunas que você usa |
| Consulta | Filtragem acontece em SQL, não em PHP com array_filter |
Buscar apenas as linhas necessárias |
| Consulta | Grandes conjuntos de resultados são paginados com OFFSET ... FETCH |
Paginar grandes conjuntos de resultados |
| Consulta | Conjunto de procedimentos armazenados SET NOCOUNT ON |
Preferir SET NOCOUNT ON |
| Inserções | Inserções em massa usam parâmetros com valor de tabela, não loops por linha | Inserir dados de forma eficiente |
| Statements |
PDO::ATTR_EMULATE_PREPARES é definido como false |
Preferir preparações nativas |
| Statements | A aplicação reutiliza instruções preparadas entre execuções | Reutilizar declarações preparadas |
| Cursors | O aplicativo usa o cursor padrão somente de avanço, a menos que seja necessário armazenamento em buffer. | Gerencie cursores e memória |
| Memory | Grandes valores binários e de caracteres são transmitidos por streaming, não materializados | Transmitir valores binários grandes e valores de caractere |
| Tempo de espera | O tempo limite da instrução está definido em todas as consultas voltadas para o usuário | Tempo limite da instrução |
| Routing | Cargas de trabalho somente de leitura definidas para ApplicationIntent=ReadOnly, onde existe uma réplica |
Roteamento de cargas de trabalho somente leitura |
| Observability | A Repositório de Consultas é ativada e revisada regularmente | Repositório de Consultas |
Conteúdo relacionado
- Pool de conexões (Drivers da Microsoft para PHP para SQL Server)
- Opções de conexão
- Tipos de cursor (driver PDO_SQLSRV)
- Tipos de cursor (driver SQLSRV)
- Usar parâmetros com valor de tabela (PHP)
- Solucionar problemas dos Drivers da Microsoft para PHP para SQL Server
- Monitorar o desempenho usando o Repositório de Consultas