Azure SQL Database shows its own CPU count, labels its memory a limit in tabs, cards and get_memory_stats, and says vCores in CPU right-sizing - #4882
Merged
erikdarlingdata merged 25 commits intoOct 1, 2026
Conversation
…'s hardware On an Azure SQL Database the collected logical CPUs, sockets, cores per socket, hyperthread ratio and physical memory are the host's, not the database's allocation. get_server_properties (Lite and Darling) now returns those five as null with vcore_count and a hardware_note, the web Server Properties list hides them and shows the service objective and vCores, and the FinOps Server Inventory and utilization card stop presenting the host's memory and cores. Every other engine edition is unchanged.
…e server properties pin expects vcore_count after the clock pair
… no longer use the host's hardware On an Azure SQL Database sys.dm_os_sys_info describes the host: a 1-vCore serverless General Purpose database read 2 CPUs and 911.9 GB of memory. Three calculations still divided by or scored those values. Each now uses the database's own figure where one is collected (vcore_count from the service objective) and is not applicable otherwise. A DTU objective names no vCores, so its CPU count is not applicable and nothing is computed from the host. SQL Server and Managed Instance are unchanged. - CpuAttribution has an overload that takes the engine edition and vcore_count. On edition 5 it divides by the vCores, or omits the ratio with a not-applicable note. Both top-queries and top-procedures tools, in Lite and Darling, call it. - The FinOps utilization read resolves its CPU count through the edition in SQL, in both apps, so edition 5 never falls back to the host's count. The card shows n/a for it. - The FinOps health score leaves its memory term out on edition 5, because that term is the buffer pool's share of the host's physical memory. CPU and storage carry the score, and a tooltip says so.
…-no-host-hardware-in-math
…database gets no CPU advice The CPU count on an Azure SQL Database is now its vCore count, or none for a DTU objective, never the host's count. The test that expects the CPU rule to fire on edition 5 seeded the host's 32 CPUs with no vcore_count, which is the DTU case. It now seeds a 32-vCore objective. A new test pins that a DTU database gets no CPU advice.
…-no-host-hardware-in-math
…ry_stats, not the host On an Azure SQL Database the FinOps memory figures read memory_stats, where total_physical_memory_mb is filled from committed_target_kb. That is the database's own memory limit (1,838 MB on a 1-vCore General Purpose database), not the host's 911.9 GB. Only server_properties holds the host's memory. - The Utilization card shows Physical Memory and Buffer Pool % on every edition. On an Azure SQL Database the caption reads "Memory limit" and the verdict sentences name the database's memory limit. - The health score keeps its memory term on every edition. FinOpsHealthCalculator.Overall takes an int memory score again. - The memory and VM right-sizing rules still skip an Azure SQL Database, now because its memory comes with its service objective and cannot be resized on its own. - Comments and tests that called the memory_stats figure the host's are corrected. New tests seed memory_stats and server_properties with different values, so a read that swaps the two tables fails. - A DTU-model objective and an elastic pool both have no vCore count. The wording now names both.
…-no-host-hardware-in-math
…e stop using the host's figures On an Azure SQL Database (engine edition 5) sys.dm_os_sys_info describes the host the database runs on, so the stored cpu_count, hyperthread_ratio, socket_count, cores_per_socket and physical_memory_mb are the host's, and the max_workers_count copied from the same DMV follows the host's CPUs. This finishes what the CPU attribution and FinOps utilization change left, in Lite and Darling alike. - SERVER_HARDWARE fact: on an Azure SQL Database it carries the database's own vCores and the HADR flag and nothing else (no topology, no memory), and is not emitted when the service objective names no vCores. The LPIM advisory, which gated on the host's memory, is left out there. Both fact collectors go through one shared builder. - Plan Server Context metadata (three readers): the vCores and no RAM figure on an Azure SQL Database; the Hardware row shows the vCores alone, or is dropped for a DTU objective. - Worker Threads card and the worker ceiling the provisioning verdict reads (point-in-time, 7-day trend and Server Inventory reads): no ceiling is carried on an Azure SQL Database, the card reads n/a, and nothing is scored against the host-derived maximum. - FinOps health score: a window with no CPU sample leaves the CPU term out instead of scoring the 0 it reads as (a full 100). Applies to every edition, in the utilization card and in the Server Inventory grid, with a tooltip that says so. - Memory utilization percentage: unchanged. It divides memory_stats columns, which the collector fills from the database's own committed target, so it is already the database's figure. A characterization test pins that. The Utilization() row helper in the two AzureSqlDatabaseHostMathTests files now carries a provisioning status, so its rows are measured windows and keep their CPU term.
…/azure-sql-database-host-hardware-leftovers The base branch now keeps the memory figures on an Azure SQL Database, because they come from memory_stats and not from the host. This merge takes its side wherever the two conflict: the health score keeps its memory term on every edition, and ServerHardwareScope no longer has HealthScoreWithoutMemoryNote. What stays from this branch on top of that: - FinOpsHealthCalculator.Overall takes a nullable CPU score. A window with no CPU sample leaves the CPU term out, and memory and storage keep their weights over their own 60. - Both tabs keep the health score tooltip for that case. It is now one line that also clears the tooltip, because the memory tooltip that used to reset it is gone. - The two test helpers that build a health score row carry a provisioning status, so their rows are measured windows. The memory scope test that pinned "no tooltip on the health score" now pins "no tooltip keyed on the edition", because the CPU tooltip exists. - Tests that depended on a null memory score are removed, and the no-CPU-sample health score tests now cover edition 5 as well.
…'s own; only memory, sockets, cores per socket and hyperthread ratio are the host's (source changes; tests not yet updated)
…r real names, and update the pins to the corrected host-figure rule Four columns are the host's (physical memory, sockets, cores per socket, hyperthread ratio). cpu_count is the database's own scheduler count, so it shows again and no calculation treats it as the host's. Memory-tab captions, the CPU unit label, the database-scoped MAXDOP advice text and the NULL in-use worker count are covered by tests that fail if the source is swapped.
…tabase) and the Server Inventory note words
…fix a stale comment about cpu_count
…named after a type
…operties table, not the v_server_properties view that the Darling store does not have Both reads added a subselect for engine_edition from v_server_properties, which exists in Lite only. On PostgreSQL it failed with 42P01 (relation does not exist), so get_memory_stats and the Viewer Memory summary errored on every Darling server. They now read the base table, as the other Darling reads of server_properties do. A new source-text pin reads the service and viewer code with the comments removed. It fails when any name used after FROM or JOIN that starts with v_ is not a view the Darling store creates (PgSchemaGenerator.AllPassthroughViews and PayloadResolvingViews). It needs no database.
…s are, and the FinOps CPU right-sizing text calls the vCores vCores get_memory_stats keeps the key names total_physical_memory_mb and available_physical_memory_mb on every edition. On an Azure SQL Database they are the database's memory limit and what is left under it, and a database that has grown to its limit reads about 100% in use, which is normal there but read as OS memory pressure. On that edition only, both apps now add a memory_note that says so, built by one shared helper in ServerHardwareScope. Other editions keep the payload key for key. The FinOps CPU right-sizing recommendation printed the vCores of an Azure SQL Database as "cores". It now names them vCores, as the utilization card does, and other editions keep "cores". The Darling Viewer's rule moves into a pure builder so it can be tested without a database. Also fixes the MemoryStatsRow doc comment that said the MCP payload names the memory figures as the Memory tab does, and a test seeder comment that said a DTU objective has no CPU count of its own (its cpu_count is its own scheduler count; it names no vCore count).
…y_stats keeps both notes and reads one edition ServerHardwareScope keeps this branch's WithMemoryNote, CpuCoreNoun and host-figure helpers together with dev's MemoryStateNote, MemoryStateOrNull and MemoryStateNoteFor. get_memory_stats in both apps now takes the engine edition once and builds its payload from the row and that value. On an Azure SQL Database the payload carries engine_edition and memory_note (this branch) and a null system_memory_state with system_memory_state_note (dev). Other editions keep the stored state and carry no notes. engine_edition is null when the edition is unknown. Darling reads the edition from the registry (DarlingEngineCapability), the source every other Darling MCP not_collected answer reads, so the tool cannot disagree with its own gates. The server_properties subselect in the MCP memory read, and the edition on its row, are removed because nothing else read them. The Viewer's own reads stay on server_properties. Lite reads McpEngineCapability.EngineEditionAsync once and does not read the row's own edition, which only the desktop Memory tab uses. New pins: the payload fields follow the one edition in both directions, the Darling memory read carries no edition, and each tool reads its edition once from its capability class.
The CPU rule's guard moved into ViewerDataService.BuildCpuRightSizingRecommendation, so the pin read a method body that no longer held it and failed on every run. The CPU half now reads the builder's guard (util == null || !util.HasCpuSample || util.P95CpuPct >= 30) and the call to the builder in GetRecommendationsAsync. The VM half still reads GetRecommendationsAsync. Dropping !util.HasCpuSample from the guard fails the pin, and so does replacing the call with null.
erikdarlingdata
marked this pull request as ready for review
October 1, 2026 04:12
erikdarlingdata
marked this pull request as draft
October 1, 2026 04:15
… row's, and the Memory tab follows the tab's own
…its doc names all four
Merged
7 tasks done
erikdarlingdata
marked this pull request as ready for review
October 1, 2026 05:11
erikdarlingdata
deleted the
fix/azure-sql-database-host-hardware-leftovers
branch
October 1, 2026 05:14
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This builds on #4879, which is merged, so the diff against dev is this PR only.
What was wrong
On an Azure SQL Database (engine edition 5), #4879 treated the
cpu_countthatsys.dm_os_sys_inforeports as the host's CPU count. It hid Logical CPUs, and its comments said so. Measurements on real databases show thatcpu_countandmax_workers_countbelong to the database. Only four values are the host's:physical_memory_mb(about 912 GB)socket_countcores_per_socket(32 or 64)hyperthread_ratio(64 or 128)These figures are the database's own:
cpu_countis the number of online schedulers the database can see. It can be higher than its vCores. A 1-vCore General Purpose database reads 2, and a 2-vCore Hyperscale database reads 2.max_workers_countis the database's own worker ceiling. The same two databases read 479 and 558.memory_statsis the database's own memory limit. The same two databases read 1,838 MB and 4,476 MB.CPU percent on an Azure SQL Database is measured against the vCores that the service objective gives the database. So the CPU math uses the vCores and never falls back to
cpu_count.What changes on an Azure SQL Database
get_server_properties(Lite and Darling)cpu_count)get_server_propertiesnulls four keys, not five.total_physical_memory_mbavailable_physical_memory_mbget_memory_stats(Lite and Darling)engine_editionget_memory_stats(Lite and Darling)memory_notetotal_physical_memory_mbas the database's memory limit (its committed target), not the host's memory. It namesavailable_physical_memory_mbas what is left under that limit. It says that a utilization near 100% is normal once the database has grown to its limit. Both apps add it withServerHardwareScope.WithMemoryNote. The full text follows the table.LocalDataService. The Darling Viewer's rule moved intoViewerDataService.BuildCpuRightSizingRecommendation, so a test can run it without a database. Both useServerHardwareScope.CpuCoreNoun.current_workers_countcpu_count,vcore_countand the host's four valuescpu_countandvcore_count, and none of the host's four values. A DTU objective or an elastic pool has no vCores, so it has no fact. The fact no longer falls back to the storedcpu_count.get_analysis_factsreturns it.audit_config(Lite and Darling)audit_configadds no MAXDOP row. If those facts ever exist for such a database, the MAXDOP follows the vCores. See the MAXDOP section below.physical_memory_mb, which is the host's.The
memory_notereads as follows. Lite builds theget_memory_statspayload inMcpMemoryTools.MemoryStatsPayload, and Darling builds it inDarlingMcpDataTools.This branch merged dev, which has #4888.
get_memory_statson an Azure SQL Database keeps both of its notes.memory_noteis from this PR.system_memory_state_noteis from #4888. It explains whysystem_memory_stateis null on edition 5.engine_editionis null when the edition is unknown.memory_noteexists on edition 5 only, and it is the last key. The web reads the same payload, so its "Memory limit" captions still followengine_edition.get_memory_statsreads one edition and uses it for every field that depends on the edition. Darling reads it once from the registry, which is the source that every other Darling MCPnot_collectedanswer reads throughDarlingEngineCapability. So the tool cannot disagree with its own gates.The Darling memory read carries no edition. Its statement reads no
server_properties, andMemoryStatsRowhas noEngineEdition. Lite reads its one source once,GetSqlEngineEditionAsync, which is the newest collectedserver_propertiesrow. The Lite and Viewer latest-memory reads carry no edition either, so noMemoryStatsRowhas anEngineEditionmember. Memory > Overview reads one edition for every line in the panel: the tab's own.Code comments and test names that called
cpu_countthe host's now say that it is the database's scheduler count. One more comment is corrected. A comment in the Lite test data seeder said that a DTU objective has no CPU count of its own. It now says that itscpu_countis its own scheduler count, and that its objective names no vCore count.Surfaces that show Logical CPUs again
get_server_propertiesin Lite and in Darling: thecpu_countkey.The MAXDOP guard and the server-config target on an Azure SQL Database
The MAXDOP work in this PR is a guard, and it changes nothing that a user sees on an Azure SQL Database today. The
server_configcollector does not run there, as the first item below shows. So the CONFIG_MAXDOP and CONFIG_CTFP facts, and the maxdop and ctfp server-config targets, never exist for such a database. The MAXDOP advice andaudit_configread those facts. The advice prints its static text when they are missing, andaudit_configadds no MAXDOP row. The only vCores output that a user can reach on an Azure SQL Database is the SERVER_HARDWARE fact itself, throughget_analysis_facts.If a later change collects the CONFIG facts for such a database, the guard applies.
FactRemediation.MaxdopBasisFromreads the vCores, and the recommended MAXDOP is the smaller of the vCores and 8. Without vCores the general cap of 8 stands. The text says "vCores" and never "cores per socket", andaudit_configsays "this database's vCores". The CONFIG_MAXDOP advice namesALTER DATABASE SCOPED CONFIGURATION SET MAXDOP = nin place of the Apply button'ssp_configure. The tests feed those facts in directly.FactRemediation.ExtractServerConfigTargetsbuilds a Maxdop target from thecores_per_socketof aserver_configdrill-down row. It has no edition check. On an Azure SQL Database that target is never built, and nothing in Lite or Darling can run it. No code changed for the target, because three guards that already exist keep it right.server_configcollector does not run on an Azure SQL Database.ServerConfigCollector.AppliesToreturns false there, becausesys.configurationsis not exposed. Both apps askCollectorCatalog.AppliesTobefore they collect. So noserver_configrows exist, no CONFIG_MAXDOP fact exists, and no finding roots on it.CollectorGateSurfacePinTestsandConfigCollectorsDefinitionTestspin the gate.server_configarray from the finding's drill-down. Lite and Darling callBuildServerConfigAction, but their drill-down collectors write no such array. Only the retired Dashboard's drill-down collector writes it. That collector reads the host'scores_per_socketfrom its own tables, and the Dashboard does not support Azure SQL Database. So no Maxdop target and no recommended value exist in either app, and no card carries one.sp_configurefor such a target is the retired Dashboard'sServerConfigHandler. The sharedRenderCopyPasteCommandprintssp_configuretext for a persisted Maxdop target, but data from edition 5 never produces one.Microsoft documents the database-scoped statement as ALTER DATABASE SCOPED CONFIGURATION
SET MAXDOP = value, and its Applies to line includes Azure SQL Database. The MAXDOP page for Azure SQL Database shows the same statement. It says that the setting takes effect immediately and that the default for a new single or elastic pool database is 8.Tests
Full suites on head
15e1b1f7e: Lite: 6,648 tests, 0 failed, 0 skipped. Darling: 19,245 tests, 0 failed, 1,210 skipped, 1 not run. The live PostgreSQL tests skip because no connection is set.Memory > Overview reads one edition for every line in the panel: the tab's own. In Lite that is
_engineEdition, and in the Darling Viewer it is the registry's edition,_server.EngineEdition. So the captions, the page-file figures and the memory state cannot disagree. The latest-memory reads carry no edition. Theserver_propertiessubselects and the row members are gone.The Darling store has no
v_server_propertiesview (Lite has one). A read of that name fails on PostgreSQL with 42P01, and only the live tests see that failure. The new testDarlingReadsUseOnlyStoreViewsTestsguards every Darling read. It reads the source of four projects with the comments removed:PerformanceMonitor.Darling.Service,PerformanceMonitor.Darling.Viewer,PerformanceMonitor.Darling.AnalysisandPerformanceMonitor.Darling.Storage. It fails when a name afterFROMorJOINthat starts withv_is not a view that the store creates. It needs no database.These tests are new in the last commits:
GetMemoryStats_OnAzureSqlDatabase_CarriesAMemoryNote_ThatCallsTheTotalTheDatabasesLimit_AndNearFullNormal(Lite and Darling): on edition 5 the payload carriesmemory_note, equal to the shared text. The figures and key names are as before, and the note is the last key.GetMemoryStats_ReadFromTheStore_CarriesTheNoteOnlyWhenTheStoredEngineEditionIsAnAzureSqlDatabase(Lite): a stored edition 5 row gets the note, and a stored edition 3 row does not.GetMemoryStatsTool_BuildsItsPayloadThroughTheSharedNote(Lite and Darling): a source pin. The tool builds its payload throughServerHardwareScope.WithMemoryNote.CpuCoreNoun_IsVcoresOnAzureSqlDatabase_AndCoresEverywhereElse(Lite and Darling): the shared word is "vCores" on edition 5 and "cores" on every other edition.AzureSqlDatabase_MemoryAndVmRightSizingAdviseNothing_BecauseItsMemoryComesWithItsServiceObjective(Lite): now also pins "32 vCores" in the CPU recommendation's finding and detail, and no " cores".WithCpuSamplesOffAzureSqlDatabase_CpuMemoryAndVmRightSizingStillAdvise(Lite, editions 3 and 8): now also pins "32 cores" in the finding and detail, and no "vCores".CpuRightSizingRecommendation_OnAzureSqlDatabase_NamesTheVcores_InTheFindingAndTheDetail(Darling): runsViewerDataService.BuildCpuRightSizingRecommendationwithout a database, and pins "vCores" in the finding and detail.CpuRightSizingRecommendation_OffAzureSqlDatabase_KeepsTheWordCores(Darling, editions 3, 8 and none): pins "cores", and a savings estimate where there is a budget.CpuRightSizingRecommendation_AdvisesNothing_WithoutACpuSample_OnABusyServer_OrWithFourOrFewerCpus(Darling): pins the cases where the rule stays quiet.GetMemoryStats_ReadsTheEditionOnce_FromTheRegistry_AndEverythingEditionDependentFollowsIt(Darling): a source pin. The tool makes oneEngineEditionAsynccall, and it is the registry reader. The payload'sengine_edition,memory_noteand memory-state fields use that value.TheLatestMemoryReads_CarryNoEngineEdition_SoNoSecondSourceCanDisagreeWithTheRegistry(Darling): neither the service's memory statement nor the Viewer's memory statement readsserver_propertiesorengine_edition. NeitherMemoryStatsRowhas anEngineEditionmember.GetMemoryStats_EngineEdition_MemoryNote_AndTheStateNote_AllFollowTheOneEditionTheToolReads(Darling, editions 5, 3 and none):engine_edition,memory_note,system_memory_stateandsystem_memory_state_noteflip together with the one edition. Only edition 5 gets the note and a null state.GetMemoryStats_OffAzureSqlDatabase_KeepsTheStoredState_AndCarriesNoNotes(Lite and Darling, editions 3, 8 and none): the stored state stays,memory_noteis absent, andsystem_memory_state_noteis null. An unknown edition showsengine_editionas null.GetMemoryStats_ReadsTheEditionOnce_FromTheEngineCapabilitySource_AndEverythingEditionDependentFollowsIt(Lite): the same source pin forMcpEngineCapability.EngineEditionAsync.GetMemoryStats_EngineEdition_MemoryNote_AndTheStateNote_AllFollowTheOneEditionTheToolReads(Lite, editions 5, 3, 8 and none):engine_edition,memory_note,system_memory_stateandsystem_memory_state_noteflip together with the one edition the tool reads. Only edition 5 gets the note and a null state.TheLatestMemoryRead_CarriesNoEngineEdition_SoNoSecondSourceCanDisagreeWithTheTabsOrTheToolsOwn(Lite): a source pin. The latest-memory read takesFROM v_memory_statsand nothing fromserver_properties. It has noengine_editioncolumn, andMemoryStatsRowhas noEngineEditionproperty.TheMemoryOverview_ReadsTheTabsOwnEdition_ForItsCaptionsAndForItsOtherLines(Lite): a source pin on the Memory > Overview method. The two captions take_engineEdition. The page-file figures and the memory state take_isAzureSqlDatabase, which is that field compared with edition 5. The method reads no edition off the memory row.TheMemoryOverview_ReadsTheRegistrysEdition_ForItsCaptionsAndForItsOtherLines(Darling): a source pin on the Viewer's Memory > Overview method. All five lines that read an edition read_server.EngineEdition. They are the two captions, the two page-file figures and the memory state.CpuAndVmRightSizing_StandDownWithNoCpuSample(Darling, repointed): the CPU half reads the guard inBuildCpuRightSizingRecommendation(util == null || !util.HasCpuSample || util.P95CpuPct >= 30) and the call to it inGetRecommendationsAsync. The VM half still readsGetRecommendationsAsync.Each line below names a change that was made to the product code, then the tests that went red with it. The code was restored after each run, and
git statuswas clean after each restore. The server-config target item needs no proof, because no code changed. The shared note wording andCpuCoreNounlive inServerHardwareScope, so their proofs ran in Lite.MemoryTabTotalLabel(stats?.EngineEdition), in place of the tab's own_engineEdition. Red in Lite: TheMemoryOverview_ReadsTheTabsOwnEdition_ForItsCaptionsAndForItsOtherLines. This ran before the row'sEngineEditionmember was removed, so the change compiled.MemoryTabAvailableLabel(stats?.EngineEdition), in place of the registry's_server.EngineEdition. Red in Darling: TheMemoryOverview_ReadsTheRegistrysEdition_ForItsCaptionsAndForItsOtherLines. This ran before the row'sEngineEditionmember was removed, so the change compiled._NeverTheRowsOwn. The same change no longer compiles.CHANGELOG
The changelog line is written from this entry at release, so
CHANGELOG.mdis not edited here.SECTION: Fixed
ENTRY:
cpu_count) show again, as the database's own scheduler count. The surfaces are Server Properties (Darling web), Server Inventory (Lite and Darling Viewer) andget_server_properties. Memory, sockets, cores per socket and hyperthread ratio stay blank because the host owns them.get_server_propertiesnow nulls those four keys instead of five. The Memory tabs (Lite, Darling Viewer, Darling web) and the ready-made memory dashboard calltotal_physical_memory_mb"Memory limit" andavailable_physical_memory_mb"Available under limit".get_memory_statsaddsengine_edition. On an Azure SQL Database it also adds amemory_note, as its last key. The note says that the total is the database's memory limit and not the host's memory. It adds that a utilization near 100% is normal once the database has grown to its limit. The FinOps utilization card (Lite and Darling Viewer) says "vCores" beside the CPU count. It shows Worker Threads in use as "n/a" instead of 0 when the count was not collected. The FinOps CPU right-sizing recommendation (Lite and Darling Viewer) says "vCores" where it said "cores". The storedcurrent_workers_count, its reads and the provisioning verdict keep NULL as unknown. The FinOps health score (Lite and Darling Viewer) leaves the CPU term out of a window with no CPU sample, on every edition. The SERVER_HARDWARE analysis fact, whichget_analysis_factsreturns, carries the vCores and none of the host's memory, sockets, cores per socket or hyperthread ratio. The lock-pages-in-memory advisory is skipped. The plan viewer Server Context card shows the vCores, or n/a for a DTU objective or an elastic pool, and no memory. The top-queries and top-procedures tools describecpu_countas the database's scheduler count in their CPU ratio note.REF:
[Azure SQL Database shows its own CPU count, labels its memory a limit in tabs, cards and get_memory_stats, and says vCores in CPU right-sizing #4882]: Azure SQL Database shows its own CPU count, labels its memory a limit in tabs, cards and get_memory_stats, and says vCores in CPU right-sizing #4882