1

I have this table in one of my databases:

IF OBJECT_ID('[dbo].[repl_Gender_Type]') IS NOT NULL 
DROP TABLE [dbo].[repl_Gender_Type] 
GO
CREATE TABLE [dbo].[repl_Gender_Type] ( 
[Gender_TypeID]  CHAR(1)                          NOT NULL,
[Gender_Desc]    VARCHAR(20)                      NOT NULL,
[Create_Date]    DATETIME                         NOT NULL,
[Create_Userid]  VARCHAR(20)                      NOT NULL,
CONSTRAINT   [PK__Gender__46DD686B]  PRIMARY KEY NONCLUSTERED ([Gender_TypeID] asc))

there are only 3 records on it.

even after running the following command:

update statistics dbo.repl_Gender_Type with fullscan

I get no results when running the following query:

select SP.*
from  dbo.sysarticles A 
OUTER APPLY [sys].[dm_db_stats_properties](a.objid,1) sp
where a.objid = OBJECT_ID('dbo.repl_Gender_Type')

so dm_db_stats_properties does not keep track of small tables? what is the work around to find the number of records in the table?

sys.dm_db_stats_properties returns an empty rowset under any of the following conditions:

object_id or stats_id is NULL. The specified object is not found or does not correspond to a table or indexed view. The specified

statistics ID does not correspond to existing statistics for the specified object ID.

The current user does not have permissions to view the statistics object. This behavior allows for the safe usage of sys.dm_db_stats_properties when cross applied to rows in views such as sys.objects and sys.stats.

none of the above is right, me thinks.

I like to use this script below, that comes from this question:

sp_updatestats vs Update statistics

SELECT [sch].[name] + '.' + [so].[name] AS [TableName] ,
[ss].[name] AS [Statistic],
[sp].[last_updated] AS [StatsLastUpdated] ,
[sp].[rows] AS [RowsInTable] ,
[sp].[rows_sampled] AS [RowsSampled] ,
[sp].[modification_counter] AS [RowModifications]
FROM [sys].[stats] [ss]
JOIN [sys].[objects] [so] ON [ss].[object_id] = [so].[object_id]
JOIN [sys].[schemas] [sch] ON [so].[schema_id] = [sch].[schema_id]
OUTER APPLY [sys].[dm_db_stats_properties]([so].[object_id],
[ss].[stats_id]) sp
WHERE [so].[type] = 'U'
AND [sp].[modification_counter] > 0--change accordingly
ORDER BY [sp].[last_updated] DESC;
  • 1
    Do you get any rows returned if you remove the OUTER APPLY? Could it be that there are no rows in dbo.sysarticles, or that you are in the wrong database? And I agree with Aaron about using sys.partitions. – Solomon Rutzky Apr 23 at 15:16
  • No it does not return anything. For the number of rows that's fine, I am using sys.dm_db_partition_stats, but I wanted to have a look at the stats as well at the same time, why not? just it does not work for very small tables that's it, even after updating the stats. – Marcello Miorelli Apr 23 at 15:34
0

Looking for row counts in stats objects is problematic. Especially since stats are not updated automatically every time a row is inserted, deleted, or modified.

Use sys.dm_db_partition_stats instead. It returns row count information for every partition in the database.

SELECT Name = QUOTENAME(sch.name) + N'.' + QUOTENAME(o.name)
    , dbps.partition_number
    , dbps.row_count
    , dbps.*
FROM sys.schemas sch
    INNER JOIN sys.objects o ON sch.schema_id = o.schema_id
    INNER JOIN sys.dm_db_partition_stats dbps ON o.object_id = dbps.object_id
WHERE o.is_ms_shipped = 0
    AND (dbps.index_id = 0 OR dbps.index_id = 1); --heap or clustered indexes only

I wrote a blog post on SQLServerScience.com that shows some of the problems with the stats properties DMV in relation to row counts. That post uses this query to obtain row counts, and shows when the stats object was last updated:

SELECT Name = QUOTENAME(sch.name) + N'.' + QUOTENAME(o.name) + N'.' + QUOTENAME(s.name)
    , ddsp.stats_id
    , last_updated = CONVERT(datetime2(1), ddsp.last_updated)
    , ddsp.rows
    , mod_count = ddsp.modification_counter
    , ddsp.unfiltered_rows
FROM sys.schemas sch
    INNER JOIN sys.objects o ON sch.schema_id = o.schema_id
    INNER JOIN sys.stats s ON o.object_id = s.object_id
    OUTER APPLY sys.dm_db_stats_properties(s.object_id, s.stats_id) ddsp
WHERE o.is_ms_shipped = 0;
-1

this is only a partial answer as I could not find out why the dm_db_stats_properties did not hold anything for that particular table.

what I really wanted though, was to have a good view on the replicated table on my publisher databases, and following in line with the comments and some other scripts I got a good enough view for my analyses using the script below:

use MY_PUBLICATION_DB
GO


DECLARE @SHOW_ONLY_SUBSCRIBED_PUBLICATION BIT = 0

SELECT 
         Publication=P.name 
        ,p.immediate_sync
        ,p.allow_anonymous
        ,p.replicate_ddl
        ,PublicationDB          = db_name()
        ,the_TableName          = OBJECT_SCHEMA_NAME(a.objid) + '.' + a.name
        ,total_number_of_rows   = REPLACE(CONVERT(VARCHAR(50),CAST(SUM (ddps.row_count) OVER (PARTITION BY ddps.OBJECT_ID)  AS MONEY),1), '.00','')             
        ,[Statistics_Updated]   = STATS_DATE(a.objid,1)
        ,dius.last_user_update
        ,DestinationServer      = s.srvname
        ,DestinationDB          = s.dest_db
        ,the_DestinationTable   = a.dest_owner + '.' + a.dest_table
        ,user_seeks             = REPLACE(CONVERT(VARCHAR(50),CAST(dius.user_seeks AS MONEY),1), '.00','')   
        ,user_scans             = REPLACE(CONVERT(VARCHAR(50),CAST(dius.user_scans AS MONEY),1), '.00','')   
        ,user_lookups           = REPLACE(CONVERT(VARCHAR(50),CAST(dius.user_lookups AS MONEY),1), '.00','')   
        ,user_updates           = REPLACE(CONVERT(VARCHAR(50),CAST(dius.user_updates AS MONEY),1), '.00','')   
        ,dius.last_user_seek
        ,dius.last_user_scan        
        ,dius.last_user_lookup  

FROM dbo.syspublications P 

INNER JOIN dbo.sysarticles A 
        ON P.pubid = A.pubid

LEFT OUTER JOIN dbo.syssubscriptions s 
             ON a.artid = s.artid 

LEFT OUTER JOIN sys.dm_db_partition_stats ddps
             ON a.objid = ddps.OBJECT_ID 
            AND ddps.index_id < 2

LEFT OUTER JOIN sys.dm_db_index_usage_stats dius 
             ON 1=1
            AND (dius.index_id=1 OR dius.index_id=0)
            AND dius.object_id = a.objid 
            AND dius.database_id = DB_ID()



WHERE 1=1
  AND 1=CASE WHEN @SHOW_ONLY_SUBSCRIBED_PUBLICATION  = 1 THEN
                CASE WHEN s.srvid > 0 THEN 1 
                     ELSE 0 
                END
             ELSE 
                CASE WHEN EXISTS(SELECT 'RADHE' FROM dbo.syssubscriptions s  WHERE s.artid = a.artid AND s.srvid > 0) THEN
                          CASE WHEN (s.srvid < 0)  THEN 0 
                               ELSE 1
                          END
                     ELSE 1
                END
        END

ORDER BY ddps.row_count DESC

and this gives me:

enter image description here

EDIT:

When looking at the output table from the script above I get:

IF OBJECT_ID('[dbo].[publications_20190423_]') IS NOT NULL 
DROP TABLE [dbo].[publications_20190423_] 
GO
CREATE TABLE [dbo].[publications_20190423_] ( 
[Publication]           SYSNAME                          NOT NULL,
[immediate_sync]        BIT                              NOT NULL,
[allow_anonymous]       BIT                              NOT NULL,
[replicate_ddl]         INT                                  NULL,
[PublicationDB]         NVARCHAR(128)                        NULL,
[the_TableName]         NVARCHAR(257)                        NULL,
[total_number_of_rows]  VARCHAR(8000)                        NULL,
[Statistics_Updated]    DATETIME                             NULL,
[last_user_update]      DATETIME                             NULL,
[DestinationServer]     SYSNAME                              NULL,
[DestinationDB]         SYSNAME                              NULL,
[the_DestinationTable]  NVARCHAR(257)                        NULL,
[user_seeks]            VARCHAR(8000)                        NULL,
[user_scans]            VARCHAR(8000)                        NULL,
[user_lookups]          VARCHAR(8000)                        NULL,
[user_updates]          VARCHAR(8000)                        NULL,
[last_user_seek]        DATETIME                             NULL,
[last_user_scan]        DATETIME                             NULL,
[last_user_lookup]      DATETIME                             NULL)

To reduce the varchar(8000) to varchar(50) I had to use this little trick.

  • This doesn't answer the question you asked. If you want to monitor replication, you should ask a question about that. – Max Vernon Apr 24 at 13:07
  • This answer shows the work around that I did, and it is all working fine now, as I re-applied the stats. Thank you. – Marcello Miorelli Apr 24 at 13:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.