Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Tento článek popisuje, jak psát rychlý PHP kód na SQL Server, Azure SQL Database, Azure SQL Managed Instance, Azure Synapse Analytics a SQL databázi v Microsoft Fabric. Pokyny se vztahují jak na SQLSRV, tak na PDO_SQLSRV, které obsahují stejný základní Microsoft ODBC ovladač pro SQL Server.
Začněte s největšími změnami
Pokud můžete provést jen tři změny, udělejte tyto změny:
- Povolte poolování připojení. Navázání nového TLS připojení k SQL Server trvá desítky až stovky milisekund v závislosti na síťové cestě a TLS vyjednávání. Opětovné použití sdílených spojení eliminuje tyto náklady na požadavek. Viz Efektivně spravujte spojení.
- Načítej jen ty sloupce a řádky, které potřebuješ.
SELECT *a neohraničené dotazy jsou nejčastějšími příčinami pomalých endpointů. Viz Dotazujte jen to, co potřebujete. - Pro hromadné vklady použijte parametry s hodnotami tabulky. Pro stovky a více řádků jsou parametry s hodnotou tabulky (TVP) obvykle mnohem rychlejší než příkazy
INSERTzpracovávané po jednotlivých řádcích a jejich výkon roste lineárně s počtem řádků. Viz Vložit data efektivně.
Efektivně spravujte spojení
Navázání spojení je nejnákladnější operace, kterou ovladač vykonává. Téměř každé šetření výkonu v PHP končí opravou správy spojení.
Povolení sdružování připojení
Pooling opětovně používá připojení ODBC mezi požadavky PHP namísto jejich ukončování na konci každého požadavku. Objekt připojení je zahozen, když váš skript skončí, ale podkladový popisovač ODBC zůstává aktivní ve fondu správce ovladačů ODBC a je znovu použit při dalším požadavku, který používá stejný připojovací řetězec.
Windows: Sdružování připojení je ve výchozím nastavení zapnuté. Pro potvrzení tuto ConnectionPooling možnost vynechte ve svém DSN. Chcete-li pro ladění deaktivovat sdružování, nastavte ConnectionPooling=0.
Linux a macOS: Sdružování připojení není na těchto platformách možností v DSN. Povolte to ve správci ovladačů nastavením Pooling=Yes v části [ODBC] v odbcinst.ini a nastavte kladný CPTimeout v sekci ovladače. Příklady:
[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
Najděte skutečnou cestu knihovny pomocí odbcinst -q -d -n "ODBC Driver 18 for SQL Server" nebo ls /opt/microsoft/msodbcsql18/lib64/. Název souboru vkládá nainstalovanou verzi ovladače ODBC a mění se s každým vydáním.
CPTimeout (za pár sekund) Ovládá, jak dlouho zůstávají nečinné spoje v poolu, než se uzavře. Nastavte ji dostatečně vysoko, aby většina požadavků našla spojení z fondu, ale dostatečně nízko, aby se zastaralá připojení k serveru po failoveru vyřadila v rozumně krátké době. 60 až 300 sekund funguje dobře pro většinu webových zátěží.
Podrobnosti viz sdružování připojení.
Pochopte náklady na první dotaz
Ve výchozím nastavení je povoleno více aktivních sad výsledků (MARS). Když jsou MARS i pooling spojení aktivní, ovladač resetuje poolované spojení při prvním dotazu a tento reset ignoruje časový limit dotazu, který jste nastavili pro ten první dotaz. Pozdější dotazy na stejné spojení obvykle respektují časovou pauzu. Pokud u sdružené úlohy nastavíte agresivní časové limity pro první dotaz, zohledněte toto chování, nebo pomocí MultipleActiveResultSets=false vypněte MARS, pokud ho nepotřebujete. Viz poznámku o MARS a sdružování v sekci Connection pooling.
Trvalá PDO připojení nejsou podporována
PDO_SQLSRV odmítá PDO::ATTR_PERSISTENT. Nastavení v konstruktoru vyvolá výjimku:
SQLSTATE[IMSSP]: An unsupported attribute was designated on the PDO object.
Používejte sdružování připojení ODBC pro opětovné použití napříč požadavky. Je to nativní mechanismus ovladače, funguje jak pro PDO_SQLSRV, tak pro SQLSRV, a ukončuje nečinná připojení při CPTimeout (což také zajišťuje správné obnovování tokenu Microsoft Entra).
Opětovné použití připojení v rámci jednoho požadavku
I při poolování znamená otevření nového PDO nebo SQLSRV připojení ODBC zpět pro načtení a ověření poolovaného handle. Otevřete spojení jednou za každý požadavek a pošlete ho do každé funkce, která ho potřebuje.
Tip
Stačí kontejner pro injekci závislostí nebo líný přístupák. Jde o to, aby se nešlo new PDO(...) přímo uprostřed obslužného modulu požadavků.
Dotazujte se pouze na to, co potřebujete
Síťové komunikace tam a zpět a materializace sady výsledků jsou hlavními faktory latence dotazů u většiny pracovních zátěží v PHP. Opravy jsou stejné, které platí pro každou vrstvu přístupu k databázi.
Vyberte pouze sloupce, které používáte
SELECT * Vytahuje všechny sloupce, včetně sloupců varchar(max) a varbinary(max), které převyšují data, která skutečně spotřebujete. Pojmenujte sloupce:
<?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");
Přines jen ty řádky, které potřebuješ
Přesuňte filtrování na SQL Server. Nikdy nestahujte celou tabulku do PHP jen kvůli tomu, abyste ji filtrovali ve smyčce 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);
Stránkování velkých sad výsledků
Pro zobrazení seznamu, které ukazuje několik stovek řádků z milionů, nevracejte všechny řádky a nechte to na klientovi, ať si to vyřeší. Použijte stránkování na straně serveru s 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);
}
Vyberte správnou metodu načtení
- Použijte
fetch(PDO::FETCH_ASSOC)ve smyčce pro postupné zpracování, pokud nepotřebujete mít všechny řádky současně v paměti. - Použijte
fetchAll(PDO::FETCH_ASSOC), když volající skutečně potřebuje celou sadu (například při vykreslení úplné odpovědi JSON). - Použijte
fetchColumn(), když vám záleží jen na jednom skaláru (,COUNTSUM, neboMAX). - Používejte
PDO::FETCH_KEY_PAIRneboPDO::FETCH_UNIQUEk vytvoření vyhledávacích slovníků bez druhého průchodu.
Numerické režimy načítání (PDO::FETCH_NUM) jsou o něco rychlejší než asociativní režimy načítání, protože přeskakují vytváření mapy názvů sloupců. Preferujte jasnost; Přepínat jen tehdy, když profiler označí fetch overhead jako významný.
Preferujte SET NOCOUNT ON v uložených procedurách a dávkách
Každý příkaz INSERT, UPDATE a DELETE vrací token DONE_IN_PROC s počtem ovlivněných řádků, který PHP obvykle ignoruje. Token nepřidává zpáteční cestu, ale každý z nich stále stojí bajty na kabelu a trochu práce s ovladači. V proceduře s více příkazy nebo v dávce, která při jednom volání spouští stovky příkazů, se úspory nasčítají. Vypněte to:
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;
Efektivně vkládejte data
Vyberte správnou metodu vkládání podle toho, kolik řad přesouváte. Špatná volba může být 100krát pomalejší.
Méně než asi 100 řádků: připravený výrok v smyčce
Pro malé dávky spusťte jeden připravený příkaz ve smyčce:
<?php
$stmt = $conn->prepare("INSERT INTO dbo.Products (Name, Price) VALUES (?, ?)");
foreach ($products as $p) {
$stmt->execute([$p["name"], $p["price"]]);
}
Uzavřete smyčku do transakce, aby se všechna vložení potvrdila jako jeden celek a protokol se nemusel po každém řádku vyprázdnit:
<?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;
}
Stovky až miliony řádků: parametry s tabulkovou hodnotou
Parametry s tabulkovými hodnotami (TVP) odešlou celou dávku do SQL Server najednou a umožní SQL Server zpracovat sadu jako jeden příkaz. Pro dávky o stovkách a více řádků jsou TVP obvykle mnohem rychlejší než smyčka připravených výkazů a škálují lineárně s počtem řádků.
Nejprve vytvořte typ tabulky na serveru:
CREATE TYPE dbo.ProductTableType AS TABLE (
Name NVARCHAR(100),
Price DECIMAL(10, 2)
);
PDO_SQLSRV předává TVP jako asociativní pole, jehož klíčem je název typu a hodnotou je sada řádků. Spojte ji s 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();
Pro nevýchozí schéma zadejte schéma jako další prvek pole: ["ProductTableType" => $rows, "Sales"]. Pro příklady procedurální syntaxe a uložených procedur SQLSRV viz Použít parametry s tabulkovými hodnotami.
Miliony řádků: bcp nebo BULK INSERT
Pro skutečně hromadné operace (zatížení datového skladu, počáteční migrace) použijte bcp nebo BULK INSERT místo PHP. Zapisujte data do odděleného nebo nativního formátu souboru, pak spusť bcp nebo BULK INSERT z plánované úlohy, ETL kroku nebo admin skriptu.
Caution
Pokud z PHP spouštíte bcp pomocí shell_exec() nebo proc_open(), nikdy nevkládejte nedůvěryhodný vstup přímo do příkazového řádku. Používejte escapeshellarg() u každého argumentu a upřednostněte provádění zatížení mimo pásmo namísto v rámci zpracování webového požadavku.
Snižte zpáteční jízdy tam a zpět
Každá síťová cesta mezi PHP a SQL Server má pevné náklady. Když pošlete pět výpisů najednou, zaplatíte tuto cenu jednou místo pětikrát.
Spojte související příkazy do jedné dávky
Pro související operace, které se spouštějí společně, seskupte příkazy do jedné dávky a zpracujte všechny sady výsledků:
<?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);
Pro SQLSRV používejte sqlsrv_next_result k přecházení mezi sadami výsledků.
Povolte více aktivních sad výsledků, když to potřebujete
Více aktivních sad výsledků (MARS) umožňuje jednomu spojení mít více aktivních příkazů. Bez MARS nemůžete zadat nový dotaz na spojení, které má stále otevřenou sadu výsledků. Oba ovladače mají MARS ve výchozím nastavení povolenou. Chcete-li to vypnout, nastavte MultipleActiveResultSets=false ve svém připojovacím řetězci. Viz Zakázání více aktivních sad výsledků (MARS).
MARS je pohodlný, ale není zdarma. Každá aktivní sada výsledků spotřebovává zdroje na straně serveru. Je lepší nejprve plně zpracovat jednu sadu výsledků, než začnete další. Použijte MARS k odblokování skutečně vnořených kurzorových vzorů.
Vyladit připravené příkazy
Připravené příkazy šetří ovladač před opětovným parsováním SQL na serveru a umožňují vám bezpečně navázat nedůvěryhodné vstupy jako parametry.
Preferujte místní přípravky
PDO_SQLSRV může připravovat výkazy ve dvou režimech.
Nativně připravené příkazy odešlou text SQL na server jednou a při každém spuštění znovu použijí parsovaný příkaz, přičemž při každém execute() odesílají pouze hodnoty parametrů.
Emulované přípravy uchovávají SQL text v klientovi a znovu vytvářejí celý SQL řetězec s parametry interpolovanými při každém vykonání.
Nastavte PDO::ATTR_EMULATE_PREPARES => false tak, aby ovladač používal nativně připravené příkazy. Nativní přípravy umožňují SQL Server cachovat a znovu používat plán dotazů a vyhýbají se opětovnému analyzování SQL textu při každém vykonání.
<?php
$conn = new PDO($dsn, null, null, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false,
]);
Znovu použít připravené výroky
Připrav se jednou, poprav mnoho. Každé volání prepare() vyžaduje alokaci popisovače ODBC a parsování na straně serveru. V horké smyčce udržujte $stmt objekt naživu a uvnitř smyčky volejte execute() :
<?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"]]);
}
Dávejte pozor na TOP (?) a IN (?, ?, ...)
TOPvyžaduje závorky kolem parametru , SELECT TOP (?) ...takže SQL Server může počet řádků parsovat jako parametr.
IN (?, ?, ?, ?) vyžaduje pevný počet zástupných symbolů při přípravě. Pro dynamické IN velikosti seznamů buď sestavte zástupný řetězec z ověřeného počtu celých čísel, nebo seznam předejte jako parametr s tabulkovou hodnotou.
Caution
Nikdy neinterpolujte nezpracovaný uživatelský vstup do textu SQL dotazu (včetně počtu zástupných symbolů). Před sestavením zástupného řetězce přetypujte hodnotu count pomocí (int) a skutečné hodnoty vždy předávejte prostřednictvím execute() jako parametry.
Správa kurzorů a paměti
Výchozí typ kurzoru je PDO::CURSOR_FWDONLY, hasicí hadice pouze vpřed. Streamuje řádky do PHP jeden po druhém a nebufferuje, takže velká množina výsledků je omezena řádkovou pamětí místo celkového počtu řádků. To je většinou to, co chcete.
Používejte bufferované kurzory jen tehdy, když potřebujete jít zpět nebo počítat řádky
PDO::SQLSRV_CURSOR_BUFFERED (statický kurzor na straně klienta) načítá celou sadu výsledků do paměti PHP předem. Tento přístup vám umožňuje volat rowCount(), posunout se zpět a znovu použít příkaz. Ve výchozím nastavení je velikost vyrovnávací paměti omezena na 10 240 KB (10 MB) pomocí PDO::SQLSRV_ATTR_CLIENT_BUFFER_MAX_KB_SIZE a dotaz, jehož výsledná množina tento limit překročí, vrátí false namísto přetečení paměti PHP. Tento strop můžete zvýšit až k limitu paměti PHP, ale tím byste místo false návratové hodnoty dostali skutečnou Allowed memory size exhausted fatální chybu, pokud dotaz překročí nový strop. Laďte záměrně. Viz Typy kurzorů (PDO_SQLSRV).
Posuvné kurzory na straně serveru (PDO::SQLSRV_CURSOR_STATIC, PDO::SQLSRV_CURSOR_DYNAMIC, PDO::SQLSRV_CURSOR_KEYSET) se ukládají do vyrovnávací paměti na serveru místo na klientovi, takže nespotřebovávají paměť PHP. Nicméně uchovávají serverové zdroje po celou dobu kurzoru a jsou pomalejší na řádek než pouze forward.
Pro streamované čtení použijte výchozí režim pouze pro postup vpřed. Používejte buffered na klientské straně pro malé sady výsledků, když je potřeba rowCount() , nebo zpětné posouvání. Vyhněte se posouvatelným kurzorům na serveru, pokud neděláte něco konkrétního.
<?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();
Pro kompletní rozbor viz Typy kurzorů (PDO_SQLSRV) a Typy kurzorů (SQLSRV).
Streamovat velké binární a řetězcové hodnoty
Pro varbinary(max), varchar(max), nvarchar(max), xml a další velké typy použijte PHP streamy místo materializace celé hodnoty v paměti:
<?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);
Pro vkládání nebo aktualizaci s velkými hodnotami použijte SendStreamParamsAtExec=false v SQLSRV pro odesílání datových proudů v částech po sqlsrv_execute(). Podrobnosti najdete v části Odesílání dat jako proudu.
Nastavte vhodné časové limity
Časové limity jsou stejně výkonnostní nastavení jako nastavení spolehlivosti. Dlouho běžící dotazy blokují připojení v poolu a znemožňují obsloužit další požadavky.
Vypršení časového limitu příkazu
Nastavte časový limit pro každý příkaz, aby dotaz, který se vymkne kontrole, nedržel spojení z poolu na neurčito. Pro PDO_SQLSRV:
<?php
$stmt = $conn->prepare("SELECT ... FROM dbo.HugeTable ...");
$stmt->setAttribute(PDO::SQLSRV_ATTR_QUERY_TIMEOUT, 30); // seconds
$stmt->execute();
Pro SQLSRV předejte "QueryTimeout" => 30 v poli možností do sqlsrv_query nebo sqlsrv_prepare.
Nastavte hodnotu, která odpovídá vaší pracovní zátěži. Pro synchronní webový požadavek je obvykle 15 až 30 sekund. U dávkové úlohy na pozadí může být několik minut přiměřených. Nikdy nenastavujte timeout na nulu (neomezenou) v webovém požadavku.
Časový limit přihlášení
LoginTimeoutv připojovací řetězec ovládá, jak dlouho ovladač čeká na navázání spojení. Nastavte explicitní hodnotu při připojení k Azure SQL Database nebo Azure SQL Managed Instance, aby cold starty a failover-group failovery klienta nezasekly navždy. Hodnoty od 30 do 90 sekund fungují dobře pro většinu cloudových zátěží. Podrobnosti o dimenzování LoginTimeout vůči ConnectRetryCount * ConnectRetryInterval a výsledných režimech selhání naleznete v části Časový limit připojení. Pro referenci k možnosti viz Možnosti připojení.
Směrovat úlohy jen pro čtení do repliky
Pro dotazy jen pro čtení na databázi ve skupině dostupnosti Always On, Azure SQL Managed Instance nebo Azure SQL Database s horizontálním škálováním čtení nebo geografickou replikou přidejte ApplicationIntent=ReadOnly do svého připojovacího řetězce:
<?php
$dsn = "sqlsrv:Server=<listener>;Database=<database>;" .
"Encrypt=true;ApplicationIntent=ReadOnly";
Směrování pouze pro čtení posílá spojení do synchronizované sekundární repliky, čímž se práce odkládá od primární části. Kombinujte s MultiSubnetFailover=true pro co nejrychlejší připojení k vícepodsíťovým naslouchacím procesům skupin dostupnosti.
Sledujte výkon ze serveru
Časování na straně klienta vám řekne jen, jak dlouho trval dotaz od začátku do konce. Chcete-li zjistit, proč je pomalý, použijte vestavěnou diagnostiku SQL Server.
úložiště dotazů
Query Store zachycuje plány provádění, statistiky běhu a čekací statistiky pro každý dotaz v databázi. Je to ve výchozím nastavení povoleno v Azure SQL Database, Azure SQL Managed Instance a SQL databázi ve Fabric. Na SQL Server to povolte pro každou databázi:
ALTER DATABASE <database_name> SET QUERY_STORE = ON;
Poté použijte SQL Server Management Studio Query Store reporty k nalezení nejpomalejších a nejčastěji prováděných dotazů. Viz Monitorování výkonu pomocí Query Store.
Přehled výkonu dotazů Azure SQL
Pro Azure SQL Database automaticky zobrazuje Query Performance Insight portálu Azure nejvíce náročné dotazy bez jakékoli konfigurace. Další informace najdete v tématu Query Performance Insight pro službu Azure SQL Database.
SET STATISTICS pro jednorázové vyšetřování
Pro jeden dotaz, který chcete profilovat, ho spusť v SQL Server Management Studio se zapnutými statistikami:
SET STATISTICS TIME ON;
SET STATISTICS IO ON;
-- your query here
Vysoké logické hodnoty téměř vždy znamenají chybějící nebo nepoužitelný index. Vysoký čas procesoru při nízkém počtu logických čtení obvykle znamená špatný plán (odhadování parametrů, implicitní převod, který brání použití indexu, nebo skalární funkce, která znemožňuje paralelní zpracování).
Rozšířené události pro trasování na úrovni ovladače
Chcete-li přesně vidět, co ovladač odesílá serveru SQL Server (včetně skutečných hodnot parametrů, které interpoluje), zachyťte relaci Extended Events pomocí událostí rpc_completed a sql_batch_completed.
Kontrolní seznam výkonu
Použijte tento kontrolní seznam jako předběžnou kontrolu jakékoli PHP aplikace, která se připojuje k SQL Server:
| Oblasti | Zkontrolovat | Reference |
|---|---|---|
| Connection | Sdružování připojení je pro platformu povoleno a nakonfigurováno | Efektivně spravujte spojení |
| Connection | Aplikace znovu používá spojení v rámci požadavku a neotevírá spojení na dotaz | Znovu použijte spojení v rámci požadavku |
| Connection |
LoginTimeout pokrývá studené starty a převzetí služeb při selhání pro Azure SQL |
Časový limit přihlášení |
| Query | Dotazy vybírají pouze potřebné sloupce, ne SELECT * |
Vyberte pouze sloupce, které používáte |
| Query | Filtrování probíhá v SQL, ne v PHP s array_filter |
Přines jen ty řádky, které potřebuješ |
| Query | Velké sady výsledků jsou rozděleny na stránky pomocí OFFSET ... FETCH |
Stránkovat velké sady výsledků |
| Query | Sada uložených procedur SET NOCOUNT ON |
Upřednostnit SET NOCOUNT ON |
| Vložení | Hromadné vkládání používají tabulkové parametry, nikoli smyčky po řádcích | Efektivně vkládejte data |
| Statements |
PDO::ATTR_EMULATE_PREPARES je nastavená na false |
Preferujte místní přípravky |
| Statements | Aplikace znovu využívá připravené příkazy napříč prováděním | Znovu použít připravené výroky |
| Cursors | Aplikace používá výchozí kurzor pouze pro dopředání, pokud není potřeba bufferování | Správa kurzorů a paměti |
| Memory | Velké binární a znakové hodnoty jsou streamovány, nikoli materializovány | Streamovat velké binární a řetězcové hodnoty |
| Časové limity | Časový limit příkazu je nastaven pro všechny dotazy určené pro uživatele | Časový limit výroku |
| Směrování | Nastavte úlohy pouze pro čtení ApplicationIntent=ReadOnly, kde existuje replika |
Směrovat pracovní zátěže pouze pro čtení |
| Observability | Query Store je aktivován a pravidelně kontrolován | Úložiště dotazů |