Slow performance in SQL 2014 in SELECT without WHERE clause - performance
We migrated a SQL Server STANDARD 2008 (compatibility level 2005) to a SQL Server DEVELOPER 2014 (compatibility level 2008) and we notice slow performance in the 2014
SQL SERVER 2014 VERSION
Microsoft SQL Server 2014 (SP3) (KB4022619) - 12.0.6024.0 (X64)
Sep 7 2018 01:37:51
Copyright (c) Microsoft Corporation
Developer Edition (64-bit) on Windows NT 6.3 (Build 9600: ) (Hypervisor)
SQL SERVER 2008 VERSION
Microsoft SQL Server 2008 R2 (SP3-GDR) (KB4057113) - 10.50.6560.0 (X64) Dec 28 2017 15:03:48 Copyright (c) Microsoft Corporation Standard Edition (64-bit) on Windows NT 6.1 (Build 7601: Service Pack 1)
We had been reading a lot of posts about executions plans, indexes and the new SQL 2014 statictis, but in our case a single "SELECT * FROM table" without a WHERE clause, takes the double of time in SQL 2014.
This SQL sentences were run in the SQL Server Management Console
Any clue?
We attach a comparison time table
New times using SELECT * into #temp FROM table
SQL SERVER 2014 MEMORY USE
SQL SERVER 2008 MEMORY USE
RAM MAP
Memory reported by SQL Console
run spconfigure
Memory script
It can be different network configuration or there can be different disks on your servers,
so you should verify how much time your query executes WITHOUT sending result to client.
As the simplest test try to do your select into #tmp table, like this:
SELECT * into #t FROM table
And compare the execution time on both servers. Here you don't send results to client and exclude network issues.
To compare your servers performance more in depth assuming that the load on these servers is the same please update your questions with the results of this query:
SQL Server Wait Statistics
UPDATE
From the further investigation we have:
the client running on this pc is slower than on old server
the new server constantly reads from disk, PAGEIOLATCH_SH is on the
top of waits statistics and 64% is too high, server needs more RAM
This is because the new server is installed in virtual environment and its RAM is not configured ad dedicated. VM eats it so that server lacks the memory and the client also. The best solution here is to speak to Windows Admin telling him to reconfigure RAM for this server.
In case when Windows Admin doesn't want to reconfigure VM my advise is to run client on other pc so it can have all the memory it needs and Enable the Lock Pages in Memory Option (Windows)
When SQL Server account has lock pages in memory grant it will take as much memory as it needs (but <= MaxServerMemory configured) without releasing it to VM when VM claims it. This way your server will have 28Gb that was configured to it with 4Gb left to Windows that is perfect.
RAMMAP is a tool that helps you to see the RAM distribution on your server.
I attach my picture where VM was eating RAM from my server so you can see it clearly:
Here the server has 64GB of RAM but SQL Server gets only 36Gb even if it needs more, because VM claims it back from server.
Wher SQL Server account has locks pages in memory, it ignores VM claims and only MaxServerMemory configuration limits the RAM it can take.
UPDATE
Script for RAM distribution
DECLARE #OtherClerksTop INT
SET #OtherClerksTop = 5
SET nocount on
SET TRANSACTIon ISOLATIon LEVEL READ UNCOMMITTED
SET LOCK_TIMEOUT 10000
DECLARE #sql NVARCHAR(max)
DECLARE #Version VARCHAR(100)
DECLARE #ServiceName NVARCHAR(100)
SET #Version = CAST(SERVERPROPERTY('ProductVersion') AS VARCHAR(100))
SET #ServiceName = CASE WHEN ##SERVICENAME = 'MSSQLSERVER'
THEN 'SQLServer:'
ELSE 'MSSQL$' + ##SERVICENAME + ':'
END
DECLARE #Perf TABLE (object_name nvarchar(20), counter_name nvarchar(128), instance_name nvarchar(128), cntr_value BIGINT, formatted_value NUMERIC(20, 2), shortname NVARCHAR(20))
INSERT INTO #Perf(object_name, counter_name, instance_name, cntr_value, formatted_value, shortname)
SELECT
CASE
WHEN CHARINDEX ('Memory Manager', object_name)> 0 THEN 'Memory Manager'
WHEN CHARINDEX ('Buffer Manager', object_name)> 0 THEN 'Buffer Manager'
WHEN CHARINDEX ('Plan Cache', object_name)> 0 THEN 'Plan Cache'
WHEN CHARINDEX ('Buffer Node', object_name)> 0 THEN 'Buffer Node' -- 2008
WHEN CHARINDEX ('Memory Node', object_name)> 0 THEN 'Memory Node' -- 2012
WHEN CHARINDEX ('Cursor', object_name)> 0 THEN 'Cursor'
WHEN CHARINDEX ('Databases', object_name) > 0 THEN 'Databases'
ELSE NULL
END AS object_name,
CAST(RTRIM(counter_name) AS NVARCHAR(100)) AS counter_name,
RTRIM(instance_name) AS instance_name,
cntr_value,
CAST(NULL AS DECIMAL(20,2)) AS formatted_value,
SUBSTRING(counter_name, 1, PATINDEX('% %', counter_name)) shortname
FROM sys.dm_os_performance_counters
WHERE (object_name LIKE #ServiceName + 'Buffer Node%' -- LIKE is faster than =. I have no idea why
OR object_name LIKE #ServiceName + 'Buffer Manager%'
OR object_name LIKE #ServiceName + 'Memory Node%'
OR object_name LIKE #ServiceName + 'Plan Cache%')
AND (counter_name LIKE '%pages %'
OR counter_name LIKE '%Node Memory (KB)%'
OR counter_name = 'Page life expectancy'
)
OR (object_name = #ServiceName + 'Memory Manager'
AND counter_name IN ('Granted Workspace Memory (KB)', 'Maximum Workspace Memory (KB)',
'Memory Grants Outstanding', 'Memory Grants Pending',
'Target Server Memory (KB)', 'Total Server Memory (KB)',
'Cnecti Memory (KB)', 'Lock Memory (KB)',
'Optimizer Memory (KB)', 'SQL Cache Memory (KB)',
-- for 2012
'Free Memory (KB)', 'Reserved Server Memory (KB)',
'Database Cache Memory (KB)', 'Stolen Server Memory (KB)',
-- XTP
'Log Pool Memory (KB)')
)
OR (object_name LIKE #ServiceName + 'Cursor Manager by Type%'
AND counter_name = 'Cursor memory usage'
AND instance_name = '_Total'
)
-- Add UNIONt to 'Cursor memory usage'
UPDATE #Perf
SET counter_name = counter_name + ' (KB)'
WHERE counter_name = 'Cursor memory usage'
-- Cvert values from pages and KB to MB and rename counters accordingly
UPDATE #Perf
SET
counter_name = REPLACE(REPLACE(REPLACE(counter_name, ' pages', ''), ' (KB)', ''), ' (MB)', ''),
formatted_value =
CASE
WHEN counter_name LIKE '%pages' THEN cntr_value/128.
WHEN counter_name LIKE '%(KB)' THEN cntr_value/1024.
ELSE cntr_value
END
-- Delete some pre 2012 counters for 2012 in order to remove duplicates
DELETE P2008
FROM #Perf P2008
INNER JOIN #Perf P2012
on replace(P2008.object_name, 'Buffer', 'Memory') = P2012.object_name AND P2008.shortname = P2012.shortname
WHERE P2008.object_name IN ('Buffer Manager', 'Buffer Node')
-- Update counter/object names so they look like in 2012
UPDATE PC
SET
object_name = REPLACE(object_name, 'Buffer', 'Memory'),
counter_name = ISNULL(M.NewName, counter_name)
FROM #Perf PC
LEFT JOIN
(
SELECT 'Free' AS OldName, 'Free Memory' AS NewName UNION ALL
SELECT 'Database', 'Database Cache Memory' UNION ALL
SELECT 'Stolen', 'Stolen Server Memory' UNION ALL
SELECT 'Reserved', 'Reserved Server Memory' UNION ALL
SELECT 'Foreign', 'Foreign Node Memory'
) M ON M.OldName = PC.counter_name
AND NewName NOT IN (SELECT counter_name FROM #Perf WHERE object_name = 'Memory Manager')
WHERE object_name IN ('Buffer Manager', 'Buffer Node')
-- Add Memory Clerks
-- Add some Memory Clerk descriptis
IF OBJECT_ID('tempdb..#mem_clerks_desc') IS NOT NULL DROP TABLE #mem_clerks_desc
CREATE TABLE #mem_clerks_desc(type varchar(60), descripti varchar(60), is_perf_counter bit)
INSERT #mem_clerks_desc VALUES('CACHESTORE_BROKERTO','Service Broker Transmissi Object Cache', 0)
INSERT #mem_clerks_desc VALUES('CACHESTORE_COLUMNSTOREOBJECTPOOL','Column Store Object Pool', 0)
INSERT #mem_clerks_desc VALUES('CACHESTORE_OBJCP','Object Plans', 1)
INSERT #mem_clerks_desc VALUES('CACHESTORE_PHDR','Bound Trees', 1)
INSERT #mem_clerks_desc VALUES('CACHESTORE_SEHOBTCOLUMNATTRIBUTE','SE Shared Column Metadata Cache', 0)
INSERT #mem_clerks_desc VALUES('CACHESTORE_SQLCP','SQL Plans', 1)
INSERT #mem_clerks_desc VALUES('CACHESTORE_SYSTEMROWSET','System Rowset Store', 0)
INSERT #mem_clerks_desc VALUES('CACHESTORE_TEMPTABLES','Temporary Tables & Table Variables', 1)
INSERT #mem_clerks_desc VALUES('CACHESTORE_XPROC','Extended Stored Procedures', 1)
INSERT #mem_clerks_desc VALUES('MEMORYCLERK_QUERYDISKSTORE','Query Store Memory', 0)
INSERT #mem_clerks_desc VALUES('MEMORYCLERK_QUERYDISKSTORE_HASHMAP','Query Store Hash table ', 0)
INSERT #mem_clerks_desc VALUES('MEMORYCLERK_SOSMEMMANAGER','SOS Memory Manager', 0)
INSERT #mem_clerks_desc VALUES('MEMORYCLERK_SOSNODE','SOS Node', 0)
INSERT #mem_clerks_desc VALUES('MEMORYCLERK_SOSOS','SOS Memory Clerk', 0)
INSERT #mem_clerks_desc VALUES('MEMORYCLERK_SQLBUFFERPOOL','Database Cache Memory', 1)
INSERT #mem_clerks_desc VALUES('MEMORYCLERK_SQLCLR','SQL CLR', 0)
INSERT #mem_clerks_desc VALUES('MEMORYCLERK_SQLCLRASSEMBLY','SQL CLR Assembly', 0)
INSERT #mem_clerks_desc VALUES('MEMORYCLERK_SQLCNECTIPOOL','Cnecti Memory', 1)
INSERT #mem_clerks_desc VALUES('MEMORYCLERK_SQLGENERAL','SQL General', 0)
INSERT #mem_clerks_desc VALUES('MEMORYCLERK_SQLLOGPOOL','Log Pool Memory', 1)
INSERT #mem_clerks_desc VALUES('MEMORYCLERK_SQLOPTIMIZER','Optimizer Memory', 1)
-- INSERT #mem_clerks_desc VALUES('MEMORYCLERK_SQLQERESERVATIS','Granted Workspace Memory (Used+Reserved)', 0) -- Exclude completely
INSERT #mem_clerks_desc VALUES('MEMORYCLERK_SQLQUERYEXEC','SQL Query Exec', 0)
INSERT #mem_clerks_desc VALUES('MEMORYCLERK_SQLQUERYPLAN','SQL Query Plan', 0)
INSERT #mem_clerks_desc VALUES('MEMORYCLERK_SQLSERVICEBROKER','SQL Service Broker', 0)
INSERT #mem_clerks_desc VALUES('MEMORYCLERK_SQLSTORENG','SQL Storage Engine', 0)
INSERT #mem_clerks_desc VALUES('MEMORYCLERK_SQLTRACE','SQL Trace', 0)
INSERT #mem_clerks_desc VALUES('MEMORYCLERK_XE','Extended Events Engine', 0)
INSERT #mem_clerks_desc VALUES('MEMORYCLERK_XE_BUFFER','Extended Events Buffer', 0)
INSERT #mem_clerks_desc VALUES('MEMORYCLERK_XTP','In-Memory objects (XTP)', 0)
INSERT #mem_clerks_desc VALUES('OBJECTSTORE_LOCK_MANAGER','Lock Memory', 1)
INSERT #mem_clerks_desc VALUES('OBJECTSTORE_SERVICE_BROKER','Service Broker (Object Store)', 0)
INSERT #mem_clerks_desc VALUES('OBJECTSTORE_SNI_PACKET','SNI Packet (Object Store)', 0)
INSERT #mem_clerks_desc VALUES('OBJECTSTORE_XACT_CACHE','Transactis Cache (Object Store)', 0)
INSERT #mem_clerks_desc VALUES('USERSTORE_DBMETADATA','Database Metadata (User Store)', 0)
INSERT #mem_clerks_desc VALUES('USERSTORE_OBJPERM','Object Permissis (User Store)', 0)
INSERT #mem_clerks_desc VALUES('USERSTORE_SCHEMAMGR','Schema Manager (User Store)', 0)
INSERT #mem_clerks_desc VALUES('USERSTORE_TOKENPERM','Token Permissis (User Store)', 0)
IF OBJECT_ID('tempdb..#mem_clerks') IS NOT NULL DROP TABLE #mem_clerks
CREATE TABLE #mem_clerks(type varchar(60), mem_type varchar(20), pages_mb DECIMAL(20, 2))
IF CAST(SUBSTRING(#VersiON, 1, CHARINDEX('.', #Version, 1)-1) AS INT) >= 11 -- SQL 2012
BEGIN
SET #sql = '
SELECT type, mem_type, CAST(SUM(pages_mb)/1024. AS DECIMAL(20, 2)) as pages_mb
FROM
(SELECT type, pages_kb as pages, virtual_memory_committed_kb as virtual, awe_allocated_kb as awe FROM sys.dm_os_memory_clerks WHERE type <> ''MEMORYCLERK_SQLQERESERVATIONS'') AS t
UNPIVOT (pages_mb FOR mem_type IN (pages, virtual, awe)
)AS unpvt
WHERE unpvt.pages_mb > 0
GROUP BY type, mem_type'
END
ELSE
BEGIN
SET #sql = '
SELECT type, mem_type, CAST(SUM(pages_mb)/1024. AS DECIMAL(20, 2)) as pages_mb
FROM
(SELECT type, single_pages_kb as single_pages, multi_pages_kb as multi_pages, virtual_memory_committed_kb as virtual, awe_allocated_kb as awe FROM sys.dm_os_memory_clerks WHERE type <> ''MEMORYCLERK_SQLQERESERVATIS'') AS t
UNPIVOT (pages_mb FOR mem_type IN (single_pages, multi_pages, virtual, awe)
)AS unpvt
WHERE unpvt.pages_mb > 0
GROUP BY type, mem_type'
END
print #sql
INSERT #mem_clerks(type, mem_type, pages_mb)
EXEC(#SQL)
-- Build Memory Tree
DECLARE #MemTree TABLE (Id int, ParentId int, counter_name nvarchar(128), formatted_value NUMERIC(20, 2), shortname NVARCHAR(20))
--->>> EXTRA MEMORY (outside of the Buffer Pool) --- ly for SQL 2008R2 and older
IF CAST(SUBSTRING(#Version, 1, CHARINDEX('.', #Version, 1)-1) AS INT) < 11
BEGIN
-- Level 1: Total
INSERT #MemTree(Id, ParentId, counter_name, formatted_value, shortname)
SELECT
Id = 2000,
ParentId = NULL,
counter_name = 'Extra Server Memory',
formatted_value = SUM(pages_mb),
shortname = 'Extra'
FROM #mem_clerks mc
LEFT JOIN #mem_clerks_desc mcd
on mcd.type = mc.type
WHERE mem_type = 'multi_pages'
-- Level 2: Detailed
INSERT #MemTree(Id, ParentId, counter_name, formatted_value, shortname)
SELECT TOP (#OtherClerksTop)
Id = 2100,
ParentId = 2000,
counter_name = ISNULL(descripti, mc.type),
formatted_value = pages_mb,
shortname = 'Extra'
FROM #mem_clerks mc
LEFT JOIN #mem_clerks_desc mcd
on mcd.type = mc.type
WHERE mem_type = 'multi_pages'
AND pages_mb > 1.
ORDER BY pages_mb DESC
-- Level 2: 'Other Server Memory Extra' = 'Server Memory (Extra)' - SUM(Children of 'Server Memory (Extra)')
INSERT #MemTree(Id, ParentId, counter_name, formatted_value, shortname)
SELECT
Id = 2110,
ParentId = 2000,
counter_name = '<Other Memory Clerks>',
formatted_value = (SELECT SSM.formatted_value FROM #MemTree SSM WHERE Id = 2000) - SUM(formatted_value),
shortname = 'Other Extra'
FROM #MemTree
WHERE ParentId = 2000
END
---<<< EXTRA MEMORY (outside of the Buffer Pool) --- ly for SQL 2008R2 and older
------ MAIN
-- Level 1
INSERT #MemTree(Id, ParentId, counter_name, formatted_value, shortname)
SELECT
Id = 1000,
ParentId = NULL,
counter_name,
formatted_value,
shortname
FROM #Perf
WHERE object_name = 'Memory Manager' AND
counter_name IN ('Target Server Memory')
-- Level 2
INSERT #MemTree(Id, ParentId, counter_name, formatted_value, shortname)
SELECT
Id = CASE WHEN counter_name = 'Maximum Workspace Memory' THEN 1100 ELSE 1200 END,
ParentId = 1000,
counter_name,
formatted_value,
shortname
FROM #Perf
WHERE object_name = 'Memory Manager' AND
counter_name IN ('Total Server Memory', 'Maximum Workspace Memory')
UNION ALL
SELECT
Id = 1150,
ParentId = 1000,
counter_name = 'Foreign Node Memory',
formatted_value = SUM(formatted_value),
shortname = 'Foreign'
FROM #Perf
WHERE object_name = 'Memory Node' AND
counter_name IN ('Foreign Node Memory')
HAVING SUM(formatted_value) > 0
-- Level 3
INSERT #MemTree(Id, ParentId, counter_name, formatted_value, shortname)
SELECT
Id = CASE counter_name
WHEN 'Granted Workspace Memory' THEN 1110
WHEN 'Stolen Server Memory' THEN 1220
ELSE 1210
END,
ParentId = CASE counter_name
WHEN 'Granted Workspace Memory' THEN 1100
ELSE 1200
END,
counter_name,
formatted_value,
shortname
FROM #Perf
WHERE object_name = 'Memory Manager'
AND counter_name IN ('Stolen Server Memory', 'Database Cache Memory', 'Free Memory', 'Granted Workspace Memory')
-- Level 4
INSERT #MemTree(Id, ParentId, counter_name, formatted_value, shortname)
SELECT
Id = 1225,
ParentId = 1220,
counter_name = p.object_name,
formatted_value = SUM(formatted_value) - SUM(ISNULL(mc.pages_mb, 0)), -- For SQL 2008 R2 and older subtract multi_pages
p.shortname
FROM #Perf p
LEFT JOIN
(
SELECT descripti as instance_name, pages_mb
FROM #mem_clerks_desc mcd
INNER JOIN #mem_clerks mc
on mc.type = mcd.type
WHERE mc.mem_type = 'multi_pages' -- For SQL 2008 R2 and older
AND ISNULL(mcd.is_perf_counter, 0) = 1
) mc
on mc.instance_name = p.instance_name
WHERE p.object_name = 'Plan Cache'
AND p.counter_name IN ('Cache')
AND p.instance_name <> '_Total'
GROUP BY p.object_name, p.shortname
UNION ALL
SELECT
Id = 1222,
ParentId = 1220,
p.counter_name,
formatted_value = p.formatted_value - ISNULL(mc.pages_mb, 0), -- For SQL 2008 R2 and older subtract multi_pages
shortname
FROM #Perf p
LEFT JOIN
(
SELECT descripti as counter_name, pages_mb
FROM #mem_clerks_desc mcd
INNER JOIN #mem_clerks mc
on mc.type = mcd.type
WHERE mc.mem_type = 'multi_pages' -- For SQL 2008 R2 and older
AND ISNULL(mcd.is_perf_counter, 0) = 1
) mc
on mc.counter_name = p.counter_name
WHERE ((object_name = 'Memory Manager' AND shortname IN ('Cnecti', 'Lock', 'Optimizer', 'Log'))
)
AND ISNULL(formatted_value, 0) > 0
UNION ALL
SELECT -- Memory Clerks (SQL 2008)
Id = 1222,
ParentId = 1220,
T.counter_name,
T.formatted_value,
shortname = 'memory clerks'
FROM
(
SELECT TOP (#OtherClerksTop)
counter_name = ISNULL(mcd.descripti, mc.type), -- + ' ' + mc.mem_type,
formatted_value = mc.pages_mb
FROM #mem_clerks mc
LEFT JOIN #mem_clerks_desc mcd
on mcd.type = mc.type
WHERE CAST(SUBSTRING(#Version, 1, CHARINDEX('.', #Version, 1)-1) AS INT) < 11 -- SQL 2008 and older
AND mc.mem_type = 'single_pages' -- SQL 2008 and older
AND ISNULL(mcd.is_perf_counter, 0) = 0
ORDER BY pages_mb DESC
) T
UNION ALL
SELECT -- Memory Clerks (SQL 2012+)
Id = 1222,
ParentId = 1220,
T.counter_name,
T.formatted_value,
shortname = 'memory clerks'
FROM
(
SELECT TOP (#OtherClerksTop)
counter_name = ISNULL(mcd.descripti, mc.type) + CASE WHEN mc.mem_type <> 'pages' THEN ' (' + mc.mem_type + ')' ELSE '' END,
formatted_value = mc.pages_mb
FROM #mem_clerks mc
LEFT JOIN #mem_clerks_desc mcd
on mcd.type = mc.type
WHERE CAST(SUBSTRING(#Version, 1, CHARINDEX('.', #Version, 1)-1) AS INT) >= 11 -- SQL 2012 and newer
AND ((mc.mem_type = 'pages' AND ISNULL(mcd.is_perf_counter, 0) = 0)
OR mc.mem_type IN ('virtual', 'awe')
)
ORDER BY pages_mb DESC
) T
UNION ALL
SELECT
Id = 1112,
ParentId = 1110,
counter_name,
formatted_value,
shortname
FROM #Perf
WHERE object_name = 'Memory Manager'
AND shortname IN ('Reserved')
UNION ALL
SELECT
Id = P.ParentID + 1,
ParentID = P.ParentID,
'Used Workspace Memory' AS counter_name,
SUM(used_memory_kb)/1024. as formatted_value,
NULL AS shortname
FROM sys.dm_exec_query_resource_semaphores
CROSS JOIN (SELECT 1220 AS ParentID UNION ALL SELECT 1110) P
GROUP BY P.ParentID
-- Level 4 -- 'Other Stolen Server Memory' = 'Stolen Server Memory' - SUM(Children of 'Stolen Server Memory')
INSERT #MemTree(Id, ParentId, counter_name, formatted_value, shortname)
SELECT
Id = 1222,
ParentId = 1220,
counter_name = '<Other Memory Clerks>',
formatted_value = (SELECT SSM.formatted_value FROM #MemTree SSM WHERE Id = 1220) - SUM(formatted_value),
shortname = 'Other Stolen'
FROM #MemTree
WHERE ParentId = 1220
-- Level 5
INSERT #MemTree(Id, ParentId, counter_name, formatted_value, shortname)
SELECT
Id = CASE WHEN p.instance_name = 'SQL Plans' THEN 1226 ELSE 1230 END,
ParentId = 1225,
counter_name = p.instance_name,
formatted_value = formatted_value - ISNULL(mc.pages_mb, 0), -- For SQL 2008 R2 and older subtract multi_pages
p.shortname
FROM #Perf p
LEFT JOIN
(
SELECT descripti as instance_name, pages_mb
FROM #mem_clerks_desc mcd
INNER JOIN #mem_clerks mc
on mc.type = mcd.type
WHERE mc.mem_type = 'multi_pages' -- For SQL 2008 R2 and older
AND ISNULL(mcd.is_perf_counter, 0) = 1
) mc
on mc.instance_name = p.instance_name
WHERE p.object_name = 'Plan Cache'
AND p.counter_name IN ('Cache')
AND p.instance_name <> '_Total'
-- Level 6
INSERT #MemTree(Id, ParentId, counter_name, formatted_value, shortname)
SELECT
Id = 1227,
ParentId = 1226,
counter_name,
formatted_value,
shortname
FROM #Perf
WHERE (object_name = 'Memory Manager' AND shortname = 'SQL') -- SQL Cache Memory
OR object_name = 'Cursor'
-- Results:
-- PLE and Memory Grants
SELECT
[Counter Name] = P.counter_name + ISNULL(' (Node: ' + NULLIF(P.instance_name, '') + ')', ''),
cntr_value as Value,
RecommendedMinimum =
CASE
WHEN P.counter_name = 'Page life expectancy' AND R.Value <= 300 -- no less than 300
THEN 300
WHEN P.counter_name = 'Page life expectancy' AND R.Value > 300
THEN R.Value
ELSE NULL
END
FROM #Perf P
LEFT JOIN -- Recommended PLE calculatis
(
SELECT
object_name,
counter_name,
instance_name,
CEILING(formatted_value/4096.*5) * 60 AS Value -- 300 per every 4GB of Buffer Pool memory or around 60 secds (1 minute) per every 819MB
FROM #Perf PD
WHERE counter_name = 'Database Cache Memory'
) R
on R.object_name = P.object_name
AND R.instance_name = P.instance_name
WHERE
(P.object_name = 'Memory Manager'
AND P.counter_name IN ('Memory Grants Outstanding', 'Memory Grants Pending', 'Page life expectancy')
)
OR -- For NUMA
(
P.object_name = 'Memory Node' AND P.counter_name = 'Page life expectancy'
AND (
SELECT COUNT(DISTINCT instance_name)
FROM #Perf
WHERE object_name = 'Memory Node'
) > 1
)
ORDER BY P.counter_name DESC, P.instance_name
-- Get physical memory
-- You can also extract this informati from sys.dm_os_sys_info but the column names have changed starting from 2012
IF OBJECT_ID('tempdb..#msver') IS NOT NULL DROP TABLE #msver
CREATE TABLE #msver(ID int, Name sysname, Internal_Value int, Value nvarchar(512))
INSERT #msver EXEC master.dbo.xp_msver 'PhysicalMemory'
DECLARE #locked_page_allocations_mb DECIMAL(20, 2)
IF OBJECT_ID('sys.dm_os_process_memory') IS NOT NULL
SELECT #locked_page_allocations_mb = locked_page_allocations_kb / 1024.FROM sys.dm_os_process_memory
-- Physical memory, cfig parameters and Target memory
SELECT
min_server_mb = (SELECT CAST(value_in_use AS DECIMAL(20, 2)) FROM sys.configurations WHERE name = 'min server memory (MB)'),
max_server_mb = (SELECT CAST(value_in_use AS DECIMAL(20, 2)) FROM sys.configurations WHERE name = 'max server memory (MB)'),
target_mb = (SELECT formatted_value FROM #Perf WHERE object_name = 'Memory Manager' AND counter_name IN ('Target Server Memory')),
physical_mb = CAST(Internal_Value AS DECIMAL(20, 2)),
locked_pages_mb = #locked_page_allocations_mb
FROM #msver
-- Memory tree
;WITH CTE
AS
(
SELECT 0 as lvl, counter_name, formatted_value, Id, NULL AS ParentId, shortname, formatted_value as TargetServerMemory, CAST(NULL AS DECIMAL(20,2)) As Perc, CAST(NULL AS DECIMAL(20,2)) As PercOfTarget
FROM #MemTree
WHERE ParentId IS NULL
UNION ALL
SELECT CTE.lvl+1,
CAST(REPLICATE(' ', 6*(CTE.lvl)) + NCHAR(124) + REPLICATE(NCHAR(183), 3) + MT.counter_name AS NVARCHAR(128)),
MT.formatted_value, MT.Id, MT.ParentId, MT.shortname, CTE.TargetServerMemory,
CAST(ISNULL(100.0*MT.formatted_value/NULLIF(CTE.formatted_value, 0),0) AS DECIMAL(20,2)) AS Perc,
CAST(ISNULL(100.0*MT.formatted_value/NULLIF(CTE.TargetServerMemory, 0),0) AS DECIMAL(20,2)) AS PercOfTarget
FROM #MemTree MT
INNER JOIN CTE
on MT.ParentId = CTE.Id
)
SELECT
counter_name AS [Counter Name], CASE WHEN formatted_value > 0 THEN formatted_value ELSE NULL END AS [Memory MB], Perc AS [% of Parent], CASE WHEN lvl >= 2 THEN PercOfTarget ELSE NULL END AS [% of Target]
FROM CTE
ORDER BY ISNULL(Id, 10000), formatted_value DESC
Related
migrate oracle table using chunks
I am trying to download a huge table (billions of records) from oracle DB The base can hold a session only for a few hours (no idea why) So my idea is to split table for many peace's and download it using dynamic sql split query: SELECT data_object_id, file_id, relative_fno, file_batch, subobject_name, MIN (start_block_id) start_block_id, MAX (end_block_id) end_block_id, SUM (blocks) blocks FROM (SELECT o.data_object_id, e.file_id, e.relative_fno, e.block_id start_block_id, e.block_id + e.blocks - 1 end_block_id, e.blocks, CEIL (SUM(e.blocks) OVER (PARTITION BY o.data_object_id, e.file_id ORDER BY e.block_id ASC) / (SUM (e.blocks)OVER (PARTITION BY o.data_object_id,e.file_id) / 1)) file_batch FROM dba_extents e, dba_objects o, dba_tab_subpartitions tsp WHERE o.owner = :owner AND o.object_name = :object_name AND e.owner = :owner AND e.segment_name = :object_name AND o.owner = e.owner AND o.object_name = e.segment_name AND (o.subobject_name = e.partition_name OR (o.subobject_name IS NULL AND e.partition_name IS NULL)) AND o.owner = tsp.table_owner(+) AND o.object_name = tsp.table_name(+) AND o.subobject_name = tsp.subpartition_name(+)) GROUP BY data_object_id, file_id, relative_fno, file_batch ORDER BY data_object_id, file_id, relative_fno, file_batch; it splits usual table, but it doesn't work with partition or subpartition tables (when I try to download it has more or less lines than it is in DB) the queries for download I used: SELECT /*+ NO_INDEX(t) */ COLUMN_NAMES,'63_17' data_chunk_id FROM OWNER.OBJECT_NAME t WHERE ((rowid >= dbms_rowid.rowid_create(1, 846313, 63, 3057792, 0) AND rowid <= dbms_rowid.rowid_create(1, 846313, 63, 4056447, 32767)));
Check out DBMS_PARALLEL_EXECUTE. Even if you don't use it "completely", ie, to run the extract, you can use the DBMS_PARALLEL_EXECUTE.CREATE_CHUNKS_BY_ROWID routine to generate a list of rowid ranges that you can then use to run your rowid range queries that you've already written.
pl/SQL Procedure to generate values in one table from values in a different table
I am learning PL/SQL and don't really know where to start writing a procedure. I have two tables, one with a department name , id ranges from and id ranges to. And another table that needs to have all values in those ranges. -- table_a CREATE TABLE table_a ( D_ID number not null primary key, DEPT VARCHAR(10), ID_FROM VARCHAR(7), ID_TO VARCHAR(7), IS_POP varchar(1) check(IS_POP IN ('Y', 'N')) ); --values in table a INSERT INTO table_a values (1, 'abc', 'A10', 'A100', 'Y'); INSERT INTO table_a values (2, 'def', 'B10', 'B50', 'N'); INSERT INTO table_a values (3, 'ghi', 'C01', 'C25', 'N'); --table_b CREATE TABLE table_b ( D_id number, ID_NUM VARCHAR(7) primary key, STATUS VARCHAR(8) CHECK (status IN ('Free','Taken')), CONSTRAINT fk_interval FOREIGN KEY (D_id) REFERENCES table_a (D_ID) ); I am trying to write a procedure to populate table_b with values generated from table_a, where the IS_POP field has 'N', and change it to 'Y' when the values are generated. So table_b should have entries with 66 rows of something like D_id ID_NUM STATUS 2 B10 Free 2 B11 Free 2 B12 Free 2 B13 Free ... 3 C24 Free 3 C25 Free
Here's an example procedure that produces the 66 records in this example data, though I was unsure is some uncertainty about whether the zero-padding is required in TABLE_B or not. This also uses iterative DML, so could provide poor performance if used at scale, and it would not be suitable to hand a situation where TABLE_A was updated after having already being populated to TABLE_B. These things could be enhanced as required in your situation. CREATE OR REPLACE PROCEDURE POPULATE_TAB_B IS BEGIN FOR POINTER IN (SELECT D_ID, REGEXP_REPLACE(ID_FROM , '[0-9].*' , NULL) AS PREFIX, LEAST(LENGTH(REGEXP_REPLACE(ID_FROM , '[^0-9]' , NULL)) , LENGTH(REGEXP_REPLACE(ID_TO , '[^0-9]' , NULL))) AS PAD_LENGTH, TO_NUMBER(REGEXP_REPLACE(ID_FROM , '[^0-9]' , NULL)) AS FROM_NUM, TO_NUMBER(REGEXP_REPLACE(ID_TO , '[^0-9]' , NULL)) AS TO_NUM FROM TABLE_A WHERE TABLE_A.IS_POP = 'N' FOR UPDATE NOWAIT) LOOP INSERT INTO TABLE_B(D_ID , ID_NUM , STATUS) SELECT POINTER.D_ID, (POINTER.PREFIX || LPAD(TO_CHAR(((LEVEL - 1) + POINTER.FROM_NUM)) , POINTER.PAD_LENGTH , '0')), 'Free' FROM DUAL CONNECT BY LEVEL <= ((POINTER.TO_NUM + 1) - POINTER.FROM_NUM); UPDATE TABLE_A SET TABLE_A.IS_POP = 'Y' WHERE TABLE_A.D_ID = POINTER.D_ID; END LOOP; END; / Procedure created. BEGIN POPULATE_TAB_B(); END; / PL/SQL procedure successfully completed. SELECT * FROM TABLE_B ORDER BY 1 ASC, 2 ASC; D_ID ID_NUM STATUS 2 B10 Free 2 B11 Free 2 B12 Free 2 B13 Free ... 3 C08 Free 3 C09 Free 3 C10 Free 3 C11 Free ... 3 C24 Free 3 C25 Free
Add IF ELSE Condition in PL SQL stored procedure
I have a scenario where I want to add an IF ELSE condition in my below procedure: I tried like below but it is not getting compiled PROCEDURE VSAT_EXCEL_REPORT ( P_R4GSTATE IN NVARCHAR2, TBLDATA OUT SYS_REFCURSOR ) AS BEGIN OPEN TBLDATA FOR IF P_R4GSTATE = "ALL" THEN SELECT ENB.SAP_ID AS SAP_ID,CAND.CANDIDATEID AS CANDIDATE_ID,ENB.R4G_STATE AS STATE,ENB.SITE_TYPE AS SITE_TYPE,CAND.SITENAME AS SITE_NAME ,ENB.SITEID AS SITEID,ENB.PRIORITY_SITE AS PRIORITYSITE,ENB.CIRCLE AS CIRCLE, DECODE (VTS.STATUS_NAME, null, 'Fill VSAT form', VTS.STATUS_NAME) AS STATUS, ENB.LATITUDE ,ENB.LONGITUDE ,VT.SITE_DETAILS_TECHNOLOGY ,VT.SITE_DETAILS_MOUNT_TYPE ,VT.SITE_DETAILS_ANTENNA_SIZE ,VT.SITE_DETAILS_AMSL ,VT.SITE_DETAILS_PLATFORM_REQUIRED ,VT.SITE_DETAILS_PLATFORM_HEIGHT ,VT.SITE_DETAILS_ROOFTOP_SITE ,VT.SITE_DETAILS_NOOFLOORS ,VT.SITE_DETAILS_ADD_ROOFTOP_SITE ,VT.SITE_DETAILS_STRUCTURAL_STAB ,VT.SITE_DETAILS_HEIGHT_OF_ANTENNA ,VT.SITE_DETAILS_SATELLITE_BAND ,VT.ANTENNA_DISTANCE_NEAR_AIRPORT ,VT.ANTENNA_AIRPORT_NAME ,VT.GSAT_LOS_16_55E ,VT.GSAT_LOS_18_74E ,VT.GSAT_LOS_12_83E FROM R4G_OSP.ENODEB ENB INNER JOIN R4G_OSP.CANDIDATE CAND ON ENB.SAP_ID = CAND.SAP_ID LEFT JOIN TBL_VSAT_MST_DETAIL VT ON ENB.SAP_ID = VT.SAP_ID LEFT JOIN TBL_VSAT_STATUS_MST VTS ON VT.STATUS_ID = VTS.STATUS_ID WHERE ENB.SCOPE = 'EnodeB-Connected_MW' AND ENB.SITEBACKHAUL = 'MW' AND CAND.STATUS = 'Fill Vendor Survey Form' AND UPPER(STATE) IN (SELECT REGEXP_SUBSTR(UPPER(P_R4GSTATE),'[^,]+', 1, LEVEL) AS RFIELDS FROM DUAL CONNECT BY REGEXP_SUBSTR(UPPER(P_R4GSTATE), '[^,]+', 1, LEVEL) IS NOT NULL); ELSE --Some condtion END VSAT_EXCEL_REPORT;
I think it should be image like this: procedure VSAT_EXCEL_REPORT ( P_R4GSTATE in nvarchar2, TBLDATA out sys_refcursor ) as begin if P_R4GSTATE = 'ALL' then open TBLDATA for select ENB.SAP_ID as SAP_ID ,CAND.CANDIDATEID as CANDIDATE_ID ,ENB.R4G_STATE as STATE ,ENB.SITE_TYPE as SITE_TYPE ,CAND.SITENAME as SITE_NAME ,ENB.SITEID as SITEID ,ENB.PRIORITY_SITE as PRIORITYSITE ,ENB.CIRCLE as CIRCLE ,DECODE(VTS.STATUS_NAME ,null ,'Fill VSAT form' ,VTS.STATUS_NAME) as STATUS ,ENB.LATITUDE ,ENB.LONGITUDE ,VT.SITE_DETAILS_TECHNOLOGY ,VT.SITE_DETAILS_MOUNT_TYPE ,VT.SITE_DETAILS_ANTENNA_SIZE ,VT.SITE_DETAILS_AMSL ,VT.SITE_DETAILS_PLATFORM_REQUIRED ,VT.SITE_DETAILS_PLATFORM_HEIGHT ,VT.SITE_DETAILS_ROOFTOP_SITE ,VT.SITE_DETAILS_NOOFLOORS ,VT.SITE_DETAILS_ADD_ROOFTOP_SITE ,VT.SITE_DETAILS_STRUCTURAL_STAB ,VT.SITE_DETAILS_HEIGHT_OF_ANTENNA ,VT.SITE_DETAILS_SATELLITE_BAND ,VT.ANTENNA_DISTANCE_NEAR_AIRPORT ,VT.ANTENNA_AIRPORT_NAME ,VT.GSAT_LOS_16_55E ,VT.GSAT_LOS_18_74E ,VT.GSAT_LOS_12_83E from R4G_OSP.ENODEB ENB inner join R4G_OSP.CANDIDATE CAND on ENB.SAP_ID = CAND.SAP_ID left join TBL_VSAT_MST_DETAIL VT on ENB.SAP_ID = VT.SAP_ID left join TBL_VSAT_STATUS_MST VTS on VT.STATUS_ID = VTS.STATUS_ID where ENB.SCOPE = 'EnodeB-Connected_MW' and ENB.SITEBACKHAUL = 'MW' and CAND.STATUS = 'Fill Vendor Survey Form' and UPPER(STATE) in (select REGEXP_SUBSTR(UPPER(P_R4GSTATE), '[^,]+', 1, level) as RFIELDS from DUAL connect by REGEXP_SUBSTR(UPPER(P_R4GSTATE), '[^,]+', 1, level) is not null); else open TBLDATA for select * from dual; end if; end VSAT_EXCEL_REPORT;
Is this query OK? [Oracle 8i]
I've got this query in Oracle 11g [working fine]: select (case when seqnum = 1 then t.DPR_N when seqnum = cnt then '0' end) as VALUE1, (case when seqnum = 1 then t.BEGIN_DT when seqnum = cnt then t.END_DT end) as timestamp, t2.APP_NAAM || '.SUBBATCH_TRIGGER' TAGNAME1 from (select t.*,t6.*, row_number() over(partition by t.BATCH_ID, t.PLANT_UNIT,t6.DPR_ID order by t.BEGIN_DT) as seqnum, count(*) over(partition by t.BATCH_ID, t.PLANT_UNIT,t6.DPR_ID) as cnt FROM tb_unit_step t INNER JOIN tb_equipment t2 ON t2.PLANT_UNIT = t.PLANT_UNIT INNER JOIN tb_rs3 t3 ON t.BATCH_ID = t3.BATCH_ID INNER JOIN tb_cpm t9 ON t9.BACPM_ID = t3.BACPM_ID INNER JOIN tb_step t4 ON (t9.BV_ID = t4.BV_ID AND t.STAP_NR1 = t4.STAP_NR1 AND t.STAP_NR2 = t4.STAP_NR2) INNER JOIN tb_bv t5 ON t5.BV_ID = t9.BV_ID INNER JOIN tb_bv_process t6 ON t9.BV_ID = t6.BV_ID AND t6.DPR_ID = t4.DPR_ID INNER JOIN tb_ins t7 ON (t7.INS_ID = t4.INS_ID) INNER JOIN tb_cpm t8 ON t8.BV_ID = t9.BV_ID WHERE (t.BEGIN_DT > ? AND t.END_DT < ?) ) t join tb_equipment t2 on t2.plant_unit = t.plant_unit where (seqnum = 1 or seqnum = cnt); I've got to make it work on Oracle 8i [I know it's a REALLY old version, but I have no choice since it's not my DB]. I've built this query in order to get the data from Oracle 8i: [I've changed CASE WHEN for DECODE and removed all the ANSI JOINs] SELECT DECODE(SEQNUM, 1, T.DPR_N,CNT,'0') VALUE1, DECODE(SEQNUM, 1, T.BEGIN_DT,CNT,T.END_DT) TIMESTAMP, '090.' || T2.APP_NAAM || '.SUBBATCH_TRIGGER' TAGNAME1 FROM (SELECT T.*, T6.*, ROW_NUMBER() OVER(PARTITION BY T.BATCH_ID, T.PLANT_UNIT,T6.DPR_ID ORDER BY T.BEGIN_DT) SEQNUM, COUNT(*) OVER(PARTITION BY T.BATCH_ID, T.PLANT_UNIT,T6.DPR_ID) CNT FROM tb_unit_step T , tb_equipment T2 , tb_rs3 T3 , tb_cpm T9 , tb_step T4 , tb_bv T5 , tb_bv_process T6 , tb_ins T7 , tb_cpm T8 WHERE T2.PLANT_UNIT = T.PLANT_UNIT AND T.BATCH_ID = T3.BATCH_ID AND (T9.BV_ID = T4.BV_ID AND T.STAP_NR1 = T4.STAP_NR1 AND T.STAP_NR2 = T4.STAP_NR2) AND T5.BV_ID = T9.BV_ID AND (T9.BV_ID = T6.BV_ID AND T6.DPR_ID = T4.DPR_ID) AND T7.INS_ID = T4.INS_ID AND T8.BV_ID = T9.BV_ID AND (T.BEGIN_DT > '15-jul-2013' AND T.END_DT < '01-aug-2014') ) T ,tb_equipment T2 WHERE T2.PLANT_UNIT = T.PLANT_UNIT AND (T.SEQNUM = 1 OR SEQNUM = T.CNT) ; The new query is definately not OK because it's taking forever to run. So what would be the correct form of the first query in order to get data from Oracle 8i? UPDATE: Result of the query: ORA-01652: unable to extend temp segment by 128 in tablespace TEMP 01652. 00000 - "unable to extend temp segment by %s in tablespace %s" *Cause: Failed to allocate an extent of the required number of blocks for a temporary segment in the tablespace indicated. *Action: Use ALTER TABLESPACE ADD DATAFILE statement to add one or more files to the tablespace indicated. Thanks in advance!
I don't see this condition in your Oracle 8 version: t9.BACPM_ID = t3.BACPM_ID That could explain the performance problem.
Using if else blocks getting missing right parenthesis error
I'm new to Oracle and having knowledge of MS SQL. I'm trying to get a phone number depending upon the user_id from Table2 and here is the business logic: Case1: if a single match is found in Table1 then get it's respective toll free number from Table2 Case2: if no match is found in Table1 then get the default toll free number from Table2 Case3: if an multiple match is found in Table1 then for all those assigned_care_levels get the Care value from Table2 ordered by asc or desc and select the top row phone number. I wrote the following query which works fine when I run it individually. However, when I cobine it using the if else statements I'm getting the following error ERROR: ORA-00907: missing right parenthesis. Here is my code: if ((select count(distinct care_level) from Table1 where user_id = '100') > 0) select phone from Table2 where care_level in (select distinct care_level from Table1 where user_id = '100') and rownum = 1 order by care_level asc else if((select count(distinct care_level) from Table1 where user_id = '100') = 0) select phone from Table2 where care_level = 'default'
SET SERVEROUTPUT ON; DECLARE v_CARE_COUNT NUMBER := 0; v_PHONE VARCHAr2(40) := NULL; BEGIN select count(distinct care_level) into v_CARE_COUNT from Table1 where user_id = '100'; IF(v_CARE_COUNT > 0) THEN select phone into v_PHONE from Table2 where care_level in (select distinct care_level from Table1 where user_id = '100') and rownum = 1; ELSE select phone into v_PHONE from Table2 where care_level = 'default'; END IF; DBMS_OUTPUT.PUT_LINE('PHONE is <'||v_PHONE||'>'); EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('Exception : '||SQLERRM); END; / EDIT: ( AS SIngle SQL) SELECT PHONE FROM TABLE2 WHERE CARE_LEVEL in ( SELECT CARE_LEVEL FROM TABLE1 WHERE USER_ID='100' UNION SELECT CARE_LEVEL FROM TABLE1 WHERE CARE_LEVEL='default' AND NOT EXISTS (SELECT 'X' FROM TABLE1 WHERE USER_ID='100') ) AND ROWNUM = 1;
The 'else if' syntax is wrong. In Oracle you need to use 'ELSIF' and complete the whole conditional statement with an 'END IF'. The SQL statements within should also be followed with a ; Try: IF ((select count(distinct care_level) from Table1 where user_id = '100') > 0) THEN select phone from Table2 where care_level in (select distinct care_level from Table1 where user_id = '100') and rownum = 1 order by care_level asc; ELSIF ((select count(distinct care_level) from Table1 where user_id = '100') = 0) THEN select phone from Table2 where care_level = 'default'; END IF