Skip to posts
  • Publications
  • Code Library
  • Events
  • Presentations
  • Who Am I?
  • Copyright

Wayne Sheffield

My blog about SQL Server
  • Home
  • Publications
  • Code Library
  • Events
  • Presentations
  • Who Am I?
  • Copyright
  • Latest Posts
  • Latest Comments


MCM


MVP

(2017-2022)

Top 50 SQL blog 2018

Recent Posts

  • Availability Group issues fixed with Alerts
  • Using Google Chrome with SSRS
  • Speakers wanted for the Richmond (VA) SQL Server Users Group – 2020
  • T-SQL Tuesday #120 – Recap
  • T-SQL Tuesday #120 – What were you thinking? – Invitation

Top Posts

  • Using a gMSA with SQL Server
  • Service Packs and Updates - Tables and Download links
  • Working with tabs and spaces in SSMS (Day 34)
  • Checking for temporary table existence
  • Windows Virtual Accounts and SQL Server
  • Availability Group issues fixed with Alerts
  • A month of SSMS tips and tricks
  • Understanding Rebinds and Rewinds
  • Primary Replica Jobs
  • Cannot start SSAS after install in tabular mode

Archives

Categories

Tags

2020 absolute values (ABS()) Advanced Certifications analytic functions assign sequential number automation Availability Group Back To Basics case-sensitive CLR String Security clustered index common table expression Data Movement deadlock analysis Denali Double-Hop efficiency extracting data from strings Failover Functions Google Chrome import file index analysis myth order by Performance physical tally table Quirky Update Scalar UDF Inlining split string splitting strings SQL SQL 2019 SQL Server SSMS SSMS Tips SSRS String Splitter T-SQL Tuesday tally table Trusted Assembly TSQL Tuesday virtual tally table Why do you do what you do? wrapup

Blogroll

  • Dave Ballantyne
  • Noel McKinney
  • Paul Randal
  • Jack Corbett
  • Adam Machanic
  • Gianluca Sartori
  • Jason Brimhall
  • Greg Low
  • Kimberly Tripp
  • Michael Swart
  • Jen McCown
  • Rob Farley
  • Hugo Kornelis
  • Benjamin Nevarez
  • Pinal Dave

Find Heaps

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
/*
Find the heap in each database (tables without a clustered index).
Original code from:
//sqlserverpedia.com/wiki/Find_Tables_Without_Primary_Keys
Modified to
  1. Return additional columns
     (object_id, type, create_date, modify_date, last_user_update),
  2. Add table aliases to all columns.
  3. Join to sys.schemas to get the proper schema name (instead of using
     schema_name function).
  4. Use o.name (instead of using the object_name function).
  5. Add check to not include tables with a type of "S"
     (system base tables, ie: sys.sysfiles1).
  6. Get results for all databases, not just the active one.
  7. Put results from all databases into one temp table and return them
     in one query (makes copying into Excel easier).
  8. Calculate the last_user_access (max of the four last_user_ columns).
*/
 
IF OBJECT_ID('tempdb..#Heaps') IS NOT NULL DROP TABLE #Heaps;
 
SELECT DBName = db_name(),
       s.name AS [schema],
       o.name AS [table],
       o.object_id,
       o.type,
       o.create_date,
       o.modify_date,
       p.rows,
       ius.user_seeks,
       ius.user_scans,
       ius.user_lookups,
       ius.user_updates,
       ius.last_user_seek,
       ius.last_user_scan,
       ius.last_user_lookup,
       ius.last_user_update
INTO #Heaps
FROM sys.indexes i
    JOIN sys.objects o
      ON i.object_id = o.object_id
    JOIN sys.schemas s
      ON o.schema_id = s.schema_id
    JOIN sys.partitions p
      ON i.object_id = p.object_id
     AND i.index_id = p.index_id
    LEFT JOIN sys.dm_db_index_usage_stats ius
      ON i.object_id = ius.object_id
     AND i.index_id = ius.index_id
WHERE i.type_desc = 'HEAP'
  AND 1=2
ORDER BY rows DESC;
 
EXECUTE sp_msforeachdb 'INSERT INTO #Heaps
SELECT DBName = ''?'',
       s.name AS [schema],
       o.name AS [table],
       o.object_id,
       o.type,
       o.create_date,
       o.modify_date,
       p.rows,
       ius.user_seeks,
       ius.user_scans,
       ius.user_lookups,
       ius.user_updates,
       ius.last_user_seek,
       ius.last_user_scan,
       ius.last_user_lookup,
       ius.last_user_update
FROM [?].sys.indexes i
    JOIN [?].sys.objects o
      ON i.object_id = o.object_id
    JOIN [?].sys.schemas s
      ON o.schema_id = s.schema_id
    JOIN [?].sys.partitions p
      ON i.object_id = p.object_id
     AND i.index_id = p.index_id
    LEFT JOIN [?].sys.dm_db_index_usage_stats ius
      ON i.object_id = ius.object_id
     AND i.index_id = ius.index_id
WHERE i.type_desc = ''HEAP''
  AND o.type NOT IN (''S'')
ORDER BY rows desc';
 
SELECT h.*, MAX(ca1.last_user_access) AS last_user_access
FROM #Heaps h
     -- unpivot these four date columns so we can get a max from them.
     CROSS APPLY (SELECT h.last_user_seek UNION ALL
                  SELECT h.last_user_scan UNION ALL
                  SELECT h.last_user_lookup UNION ALL
                  SELECT h.last_user_update) ca1 (last_user_access)
WHERE h.DBName NOT IN ('master','model','msdb','tempdb')
GROUP BY h.DBName, h.[schema], h.[table], h.object_id, h.type,
         h.create_date, h.modify_date, h.rows,
         h.user_seeks, h.user_scans, h.user_lookups, h.user_updates,
         h.last_user_seek, h.last_user_scan, h.last_user_lookup, h.last_user_update
ORDER BY last_user_access DESC, h.DBName, h.[schema], h.[table];

Share this:

  • Click to share on X (Opens in new window) X
  • Click to share on LinkedIn (Opens in new window) LinkedIn
  • Click to email a link to a friend (Opens in new window) Email
  • Click to print (Opens in new window) Print
  • More
  • Click to share on Facebook (Opens in new window) Facebook
  • Click to share on Pinterest (Opens in new window) Pinterest
  • Click to share on Reddit (Opens in new window) Reddit

Like this:

Like Loading...
  • Comments (0)
  • Trackbacks (0)
Leave a comment Trackback

No one has commented yet.

No trackbacks yet.

Leave a Reply to let me know how you liked this postCancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Powered by WordPress Web Design by SRS Solutions © 2025 Wayne Sheffield Design by SRS Solutions
Manage Cookie Consent
To provide the best experiences, we use technologies like cookies to store and/or access device information. Consenting to these technologies will allow us to process data such as browsing behavior or unique IDs on this site. Not consenting or withdrawing consent, may adversely affect certain features and functions.
Functional Always active
The technical storage or access is strictly necessary for the legitimate purpose of enabling the use of a specific service explicitly requested by the subscriber or user, or for the sole purpose of carrying out the transmission of a communication over an electronic communications network.
Preferences
The technical storage or access is necessary for the legitimate purpose of storing preferences that are not requested by the subscriber or user.
Statistics
The technical storage or access that is used exclusively for statistical purposes. The technical storage or access that is used exclusively for anonymous statistical purposes. Without a subpoena, voluntary compliance on the part of your Internet Service Provider, or additional records from a third party, information stored or retrieved for this purpose alone cannot usually be used to identify you.
Marketing
The technical storage or access is required to create user profiles to send advertising, or to track the user on a website or across several websites for similar marketing purposes.
Manage options Manage services Manage {vendor_count} vendors Read more about these purposes
View preferences
{title} {title} {title}
%d