Investigate what loads the service and the database
Users report that Access, Excel, or Power BI is slow, or the database is busy at certain times. You want to know which requests cause it, when they arrive, and what helps.
Solution overview
The service keeps a load log in the log file next to the administration store. It groups requests into shapes: a shape is the request without its values. A hundred queries from one form that differ only in the customer number are one shape with a hundred requests. This shows that a few shapes usually carry most of the load, and the log holds none of the users' data.
| Set | Shows | Right |
|---|---|---|
LoadShapes | per shape over the last seven days: count, times, rows, bytes, errors, and advice | admin |
LoadHours | the same figures per hour, for the trend over months and the weekly pattern | admin |
SlowRequests | single requests of one second or more, with their correlation ID | admin; person and key only with load-persons |
LoadAdvice | shapes with a known remedy | admin |
LoadPersons | requests per day, shape, and person | load-persons |
The administration API describes the fields and values.
Implementation
Look at the most expensive shapes. Read
LoadShapes, sorted by total time in descending order:GET /admin/v1/odata/LoadShapes?$orderby=TotalMs desc&$top=20&$select=Id,Alias,Kind,Text,Requests,TotalMs,P95Ms,DataMs,AverageRows,Advice
Textdescribes the shape, for exampledbo.Reparaturliste read: filter=(Werk eq ?); orderby=Datum; top. IfDataMsis close toTotalMs, the time is spent in the database; ifDataMsis small, it's spent in the service or in the transfer (Bytes).Read the advice. For a shape,
LoadAdvicenames what makes it expensive regardless of the data, and what usually helps:Code Typical cause What to do wholeSetAccess opens a whole linked table; Power Query loads a table without a filter Use a form or query with a criterion; filter in Power Query before loading unindexedFilterThe filter uses a column without an index Have the database administrator create an index, or filter on an indexed column deepPagingA program pages far into a large set with $skipNarrow the set, or read on through the next link countLargeEvery page requests the total count Request $countonly when neededaggregateWholeAggregates over a whole large table Narrow the set, or have it precomputed as an indexed view expensiveStatementAn own statement takes long Check it in Query Store; store it as a procedure or view refreshLoopA form with a timer or a short refresh interval, a query with frequent automatic refresh Lengthen or turn off the interval - Recognize the pattern over time. Group
LoadHoursbyWeekday(1 = Monday) andHourOfDayto see when the service is busy, or byHourto follow the trend over weeks and months. Hour and weekday follow the server's clock. - Trace a single slow request.
SlowRequestsgives the time, duration, andCorrelationId. With the correlation ID, you find the same request in the service log and in the audit. Continue in SQL Server. Every statement the service generates carries the comment
/* wkl:<Id> */after its first keyword, where<Id>is the shape's identifier fromLoadShapes. The database administrator uses it to find the plan and its cost, for example in the plan cache:SELECT TOP (20) s.execution_count, s.total_worker_time / 1000 AS cpu_ms, s.total_logical_reads, t.text FROM sys.dm_exec_query_stats AS s CROSS APPLY sys.dm_exec_sql_text(s.sql_handle) AS t WHERE t.text LIKE N'%/* wkl:%' ORDER BY s.total_worker_time DESC;
If Query Store is turned on for the database, you find the same identifier there in
sys.query_store_query_text. You recognize the service's sessions byprogram_name=Wkl.Data.Gatewayinsys.dm_exec_sessions.Give the load to the manufacturer. If the manufacturer is to investigate where users wait, write the load to a file—through the administration with
POST /admin/v1/export-load, or on the server with `export-load`:Wkl.Data.Gateway export-load --to C:\Temp\load.json --days 30
The file is readable JSON. Check it before you send it: it contains the names of aliases, tables, and columns, but no persons, addresses, or values.
Remarks
- Visible after a minute. The service writes the collected figures once a minute.
- Own statements with the
sqlright appear with their text without literals and comments. The service doesn't change them and therefore doesn't add a/* wkl:… */comment. In SQL Server, you find them by their text or byprogram_name. - Own
Application Name. If a data source's connection string sets anApplication Nameitself, the service keeps it;program_namethen shows that name. - Load per person. Anyone who reads
LoadPersonssees who queried how much and when. Grant theload-personsright only where an evaluation per person is permitted and agreed on; by default, the daily figures are kept for seven days (Gateway:LoadLog:PersonDays). The other sets don't name any person. - What isn't counted. Requests to
/health. If more than 5,000 distinct shapes come together in one minute, the service doesn't count the rest and reports this in its log. - Cost. The load log doesn't make a request measurably longer. If you don't need it, turn it off with
Gateway:LoadLog:Enabled=false.
Related topics
- Configuration: Gateway:LoadLog—all settings
- Administration API: load log—fields, values, and
export-load - Check sign-in patterns and origins—the counterpart for sign-ins