SQL-lekérdezés-végrehajtási metrikák lekérése és lekérdezési teljesítmény elemzése a .NET SDK használatával
Cikk
A KÖVETKEZŐRE VONATKOZIK: NoSQL
Ez a cikk bemutatja, hogyan profilozza az SQL-lekérdezés teljesítményét az Azure Cosmos DB-ben a .NET SDK-ból lekért ServerSideCumulativeMetrics használatával. ServerSideCumulativeMetrics egy erősen beírt objektum, amely információkat tartalmaz a háttérbeli lekérdezések végrehajtásáról. Kumulatív metrikákat tartalmaz, amelyek összesítve vannak a kérelem összes fizikai partíciója között, az egyes fizikai partíciók metrikáinak listája és a kérelem teljes díja. Ezek a metrikák részletesebben is dokumentálva vannak a Lekérdezési teljesítmény finomhangolása című cikkben.
Lekérdezésmetrikák megállapítása
A lekérdezési metrikák erősen beírt objektumként érhetők el a .NET SDK-ban a 3.36.0-s verziótól kezdve. A verzió előtt, vagy ha másik SDK-nyelvet használ, a lekérdezési metrikákat a Diagnosticslekérdezési metrikák elemzésével kérdezheti le. Az alábbi kódminta bemutatja, hogyan kérhető le ServerSideCumulativeMetrics a FeedResponse-ből:Diagnostics
CosmosClient client = new CosmosClient(myCosmosEndpoint, myCosmosKey);
Container container = client.GetDatabase(myDatabaseName).GetContainer(myContainerName);
QueryDefinition query = new QueryDefinition("SELECT TOP 5 * FROM c");
FeedIterator<MyClass> feedIterator = container.GetItemQueryIterator<MyClass>(query);
while (feedIterator.HasMoreResults)
{
// Execute one continuation of the query
FeedResponse<MyClass> feedResponse = await feedIterator.ReadNextAsync();
// Retrieve the ServerSideCumulativeMetrics object from the FeedResponse
ServerSideCumulativeMetrics metrics = feedResponse.Diagnostics.GetQueryMetrics();
}
Lekérdezési metrikákat is lekérhet egy FeedResponse LINQ-lekérdezésből a ToFeedIterator() következő módszerrel:
ServerSideCumulativeMetrics Olyan tulajdonságot CumulativeMetrics tartalmaz, amely az egyirányú út összes partíciójára összesített lekérdezési metrikákat jelöli.
// Retrieve the ServerSideCumulativeMetrics object from the FeedResponse
ServerSideCumulativeMetrics metrics = feedResponse.Diagnostics.GetQueryMetrics();
// CumulativeMetrics is the metrics for this continuation aggregated over all partitions
ServerSideMetrics cumulativeMetrics = metrics.CumulativeMetrics;
Ezeket a metrikákat a lekérdezés összes körútja során is összesítheti. Az alábbi példa bemutatja, hogyan összesítheti a lekérdezések végrehajtási idejét egy adott lekérdezés összes körútja során a LINQ használatával:
QueryDefinition query = new QueryDefinition("SELECT TOP 5 * FROM c");
FeedIterator<MyClass> feedIterator = container.GetItemQueryIterator<MyClass>(query);
List<ServerSideCumulativeMetrics> metrics = new List<ServerSideCumulativeMetrics>();
TimeSpan cumulativeTime;
while (feedIterator.HasMoreResults)
{
// Execute one continuation of the query
FeedResponse<MyClass> feedResponse = await feedIterator.ReadNextAsync();
// Store the ServerSideCumulativeMetrics object to aggregate values after all round trips
metrics.Add(feedResponse.Diagnostics.GetQueryMetrics());
}
// Aggregate values across trips for metrics of interest
TimeSpan totalTripsExecutionTime = metrics.Aggregate(TimeSpan.Zero, (currentSum, next) => currentSum + next.CumulativeMetrics.TotalTime);
DoSomeLogging(totalTripsExecutionTime);
Particionált metrikák
ServerSideCumulativeMetrics olyan tulajdonságot PartitionedMetrics tartalmaz, amely az oda-vissza út partíciónkénti metrikáinak listája. Ha több fizikai partíciót ér el egyetlen oda-visszaúton, akkor az egyes partíciók metrikái megjelennek a listában. A particionált metrikák ServerSidePartitionedMetricsként jelennek meg, amelyek egyedi azonosítót adnak az egyes fizikai partíciókhoz, és kérnek díjat az adott partícióhoz.
// Retrieve the ServerSideCumulativeMetrics object from the FeedResponse
ServerSideCumulativeMetrics metrics = feedResponse.Diagnostics.GetQueryMetrics();
// PartitionedMetrics is a list of per-partition metrics for this continuation
List<ServerSidePartitionedMetrics> partitionedMetrics = metrics.PartitionedMetrics;
Ha az összes körút során halmozódik fel, a partíciónkénti metrikák lehetővé teszik annak megtekintését, hogy egy adott partíció teljesítményproblémákat okoz-e másokhoz képest. Az alábbi példa bemutatja, hogyan csoportosíthatja az egyes utak partíciómetrikáit a LINQ használatával:
QueryDefinition query = new QueryDefinition("SELECT TOP 5 * FROM c");
FeedIterator<MyClass> feedIterator = container.GetItemQueryIterator<MyClass>(query);
List<ServerSideCumulativeMetrics> metrics = new List<ServerSideCumulativeMetrics>();
while (feedIterator.HasMoreResults)
{
// Execute one continuation of the query
FeedResponse<MyClass> feedResponse = await feedIterator.ReadNextAsync();
// Store the ServerSideCumulativeMetrics object to aggregate values after all round trips
metrics.Add(feedResponse.Diagnostics.GetQueryMetrics());
}
// Group metrics by partition key range id
var groupedPartitionMetrics = metrics.SelectMany(m => m.PartitionedMetrics).GroupBy(p => p.PartitionKeyRangeId);
foreach(var partitionGroup in groupedPartitionMetrics)
{
foreach(var tripMetrics in partitionGroup)
{
DoSomethingWithMetrics();
}
}
A lekérdezési kérelem díjának lekérése
Az egyes lekérdezések által felhasznált kérelemegységeket rögzítheti a költséges lekérdezések vagy a nagy átviteli sebességet használó lekérdezések vizsgálatához. A teljes kérelemdíj lekérhető a tulajdonság használatával, TotalRequestCharge vagy megtekintheti az egyes partíciók kérelemdíját az RequestCharge egyes ServerSidePartitionedMetrics visszaadott tulajdonságok használatával.ServerSideCumulativeMetrics
A kérelem teljes díja a következő tulajdonság használatával is elérhető: .</a0RequestCharge> Ha többet szeretne megtudni arról, hogyan kérheti le a kérelem díját az Azure Portalon és a különböző SDK-kban, tekintse meg a kérelemegységek díjáról szóló cikket.
QueryDefinition query = new QueryDefinition("SELECT TOP 5 * FROM c");
FeedIterator<MyClass> feedIterator = container.GetItemQueryIterator<MyClass>(query);
while (feedIterator.HasMoreResults)
{
// Execute one continuation of the query
FeedResponse<MyClass> feedResponse = await feedIterator.ReadNextAsync();
double requestCharge = feedResponse.RequestCharge;
// Log the RequestCharge how ever you want.
DoSomeLogging(requestCharge);
}
A lekérdezés végrehajtási idejének lekérése
A lekérdezési metrikákból minden egyes úthoz rögzítheti a lekérdezések végrehajtási idejét. A kérelmek késésének vizsgálatakor fontos megkülönböztetni a lekérdezések végrehajtási idejét más késési forrásoktól, például a hálózati átviteli időtől. Az alábbi példa bemutatja, hogyan kérhet le kumulatív lekérdezésvégrehajtási időt minden egyes körúthoz:
QueryDefinition query = new QueryDefinition("SELECT TOP 5 * FROM c");
FeedIterator<MyClass> feedIterator = container.GetItemQueryIterator<MyClass>(query);
TimeSpan cumulativeTime;
while (feedIterator.HasMoreResults)
{
// Execute one continuation of the query
FeedResponse<MyClass> feedResponse = await feedIterator.ReadNextAsync();
ServerSideCumulativeMetrics metrics = response.Diagnostics.GetQueryMetrics();
cumulativeTime = metrics.CumulativeMetrics.TotalTime;
}
// Log the elapsed time
DoSomeLogging(cumulativeTime);
Az index kihasználtságának lekérése
Az index kihasználtságának megtekintése segíthet a lassú lekérdezések hibakeresésében. Azok a lekérdezések, amelyek nem tudják használni az indexet, az eredményhalmaz visszaadása előtt a tároló összes dokumentumának teljes vizsgálata következik be.
Íme egy példa egy vizsgálati lekérdezésre:
SELECT VALUE c.description
FROM c
WHERE UPPER(c.description) = "BABYFOOD, DESSERT, FRUIT DESSERT, WITHOUT ASCORBIC ACID, JUNIOR"
A lekérdezés szűrője az UPPER rendszerfüggvényt használja, amely nem az indexből származik. A lekérdezés nagy gyűjteményen való végrehajtása az alábbi lekérdezési metrikákat eredményezte az első folytatáshoz:
QueryMetrics
Retrieved Document Count : 60,951
Retrieved Document Size : 399,998,938 bytes
Output Document Count : 7
Output Document Size : 510 bytes
Index Utilization : 0.00 %
Total Query Execution Time : 4,500.34 milliseconds
Query Preparation Time : 0.2 milliseconds
Index Lookup Time : 0.01 milliseconds
Document Load Time : 4,177.66 milliseconds
Runtime Execution Time : 407.9 milliseconds
Document Write Time : 0.01 milliseconds
Figyelje meg a lekérdezési metrikák kimenetének alábbi értékeit:
Ez a lekérdezés 60 951 dokumentumot töltött be, összesen 399 998 938 bájtot. A ennyi bájt betöltése magas költséggel jár, vagy a kérelemegység díja. A lekérdezés végrehajtása is hosszú időt vesz igénybe, ami a teljes eltöltött idő tulajdonsággal egyértelmű:
Total Query Execution Time : 4,500.34 milliseconds
Ez azt jelenti, hogy a lekérdezés végrehajtása 4,5 másodpercig tartott (és ez csak egy folytatás volt).
A példa lekérdezés optimalizálásához kerülje az UPPER használatát a szűrőben. Ehelyett a dokumentumok létrehozásakor vagy frissítésekor az c.description értékeket minden nagybetűbe be kell szúrni. A lekérdezés ezután a következő lesz:
SELECT VALUE c.description
FROM c
WHERE c.description = "BABYFOOD, DESSERT, FRUIT DESSERT, WITHOUT ASCORBIC ACID, JUNIOR"
Ez a lekérdezés mostantól kiszolgálható az indexből. Másik lehetőségként számítási tulajdonságok használatával indexelheti a rendszerfüggvények vagy összetett számítások eredményeit, amelyek egyébként teljes vizsgálatot eredményeznének.
A lekérdezés teljesítményének finomhangolásáról a Lekérdezési teljesítmény finomhangolása című cikkben talál további információt.
Hatékony lekérdezések írása, indexelési szabályzatok létrehozása, erőforrások kezelése és kiépítése az SQL API-ban és az SDK-ban a Microsoft Azure Cosmos DB-vel.