views:

65

answers:

2

I have a function that writes 3 lines into a empty table like so:

INSERT [dbo].[yaf_ForumAccess] ([GroupID], [ForumID], [AccessMaskID]) VALUES (1, 8, 1) 
INSERT [dbo].[yaf_ForumAccess] ([GroupID], [ForumID], [AccessMaskID]) VALUES (2, 8, 4)
INSERT [dbo].[yaf_ForumAccess] ([GroupID], [ForumID], [AccessMaskID]) VALUES (3, 8, 3)

For some reason only the third query takes a long time to execute - and with each insert it grows longer.

Profiler Image Profiler Image

I have tried disabling all constraints on the table - same result. I just can't figure out why the first two would run so fast - and the last one would take so long.

Any help would be greatly appreciated.

Here is the statistics for a query ran MSSMS:

Query:

ALTER TABLE [dbo].[yaf_ForumAccess] NOCHECK CONSTRAINT ALL
INSERT [dbo].[yaf_ForumAccess] ([GroupID], [ForumID], [AccessMaskID]) VALUES (1, 9, 1) 
INSERT [dbo].[yaf_ForumAccess] ([GroupID], [ForumID], [AccessMaskID]) VALUES (2, 9, 4)
INSERT [dbo].[yaf_ForumAccess] ([GroupID], [ForumID], [AccessMaskID]) VALUES (3, 9, 3)
ALTER TABLE [dbo].[yaf_ForumAccess] CHECK CONSTRAINT ALL

Stats:

alt text
Stats

STATS IO ON:

Table 'yaf_vaccess_group'. Scan count 0, logical reads 3, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'yaf_UserGroup'. Scan count 1, logical reads 709, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'yaf_AccessMask'. Scan count 0, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'yaf_Group'. Scan count 0, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 2, logical reads 7, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'yaf_ForumAccess'. Scan count 0, logical reads 4, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(1 row(s) affected)

(1 row(s) affected)
Table 'yaf_vaccess_group'. Scan count 0, logical reads 8, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'yaf_UserGroup'. Scan count 1, logical reads 709, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'yaf_AccessMask'. Scan count 0, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'yaf_Group'. Scan count 0, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 2, logical reads 7, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'yaf_ForumAccess'. Scan count 0, logical reads 4, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(1 row(s) affected)

(1 row(s) affected)
Table 'yaf_vaccess_group'. Scan count 0, logical reads 1340999, physical reads 0, read-ahead reads 3326, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'yaf_UserGroup'. Scan count 1, logical reads 709, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'yaf_Group'. Scan count 0, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'yaf_AccessMask'. Scan count 0, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 2, logical reads 7, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'yaf_ForumAccess'. Scan count 0, logical reads 4, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(1 row(s) affected)

(1 row(s) affected)


yaf_vaccess_group View:

CREATE VIEW [dbo].[yaf_vaccess_group]
WITH SCHEMABINDING
AS
        select
            b.UserID,
            c.ForumID,
            d.AccessMaskID,
            b.GroupID,
            ReadAccess      = convert(int,d.Flags & 1),
            PostAccess      = convert(int,d.Flags & 2),
            ReplyAccess     = convert(int,d.Flags & 4),
            PriorityAccess  = convert(int,d.Flags & 8),
            PollAccess      = convert(int,d.Flags & 16),
            VoteAccess      = convert(int,d.Flags & 32),
            ModeratorAccess = convert(int,d.Flags & 64),
            EditAccess      = convert(int,d.Flags & 128),
            DeleteAccess    = convert(int,d.Flags & 256),
            UploadAccess    = convert(int,d.Flags & 512),
            DownloadAccess  = convert(int,d.Flags & 1024),
            AdminGroup      = convert(int,e.Flags & 1)
        from
            [dbo].[yaf_UserGroup] b
            INNER JOIN [dbo].[yaf_ForumAccess] c on c.GroupID=b.GroupID
            INNER JOIN [dbo].[yaf_AccessMask] d on d.AccessMaskID=c.AccessMaskID
            INNER JOIN [dbo].[yaf_Group] e on e.GroupID=b.GroupID

CREATE UNIQUE CLUSTERED INDEX [yaf_vaccess_group_UserForum_PK] ON [dbo].[yaf_vaccess_group] 
(
    [UserID] ASC,
    [ForumID] ASC,
    [AccessMaskID] ASC,
    [GroupID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO

STATS IO ON w/ 4 Inserts:

Table 'yaf_vaccess_group'. Scan count 0, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'yaf_UserGroup'. Scan count 1, logical reads 709, physical reads 0, read-ahead reads 7, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'yaf_AccessMask'. Scan count 0, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'yaf_Group'. Scan count 0, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 2, logical reads 7, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'yaf_ForumAccess'. Scan count 0, logical reads 6, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(1 row(s) affected)

(1 row(s) affected)
Table 'yaf_vaccess_group'. Scan count 0, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'yaf_UserGroup'. Scan count 1, logical reads 709, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'yaf_AccessMask'. Scan count 0, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'yaf_Group'. Scan count 0, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 2, logical reads 7, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'yaf_ForumAccess'. Scan count 0, logical reads 4, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(1 row(s) affected)

(1 row(s) affected)
Table 'yaf_vaccess_group'. Scan count 0, logical reads 1220894, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'yaf_UserGroup'. Scan count 1, logical reads 709, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'yaf_Group'. Scan count 0, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'yaf_AccessMask'. Scan count 0, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 2, logical reads 7, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'yaf_ForumAccess'. Scan count 0, logical reads 4, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(1 row(s) affected)

(1 row(s) affected)
Table 'yaf_vaccess_group'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'yaf_UserGroup'. Scan count 1, logical reads 709, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'yaf_AccessMask'. Scan count 0, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 2, logical reads 7, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'yaf_ForumAccess'. Scan count 0, logical reads 4, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(1 row(s) affected)

(1 row(s) affected)
+2  A: 

From what you've shown, it's not the third query that is taking the time, its the part that is actually turning on the check constraints.

When the constraint is turned back on it has to validate that all of the records are good. This means scanning the entire table. Depending on size, it's probably IO bound and beating the crap out of your harddrives.

So, I think you need to make a decision. Either drop the constraints completely or stop flipping them on and off.

Chris Lively
Now you point it out, it's obvious! When Chris wrote "I have tried disabling all constraints on the table - same result". I, probably inappropriately, assumed this was happening even without the ALTER TABLE statements. But I think you're right.
Daniel Renshaw
Nope - it happen with the check constrains removed. I just put those in to make it easier to test. Also when I step through the code its always that 3rd insert that stalls for awhile.
Chris
Well - let me turn it back off and test again
Chris
Yep - same result. ~30 seconds on the 3rd insert.
Chris
Can you add a 4th query to the bunch and test that?
Chris Lively
Now I'm thinking it may have to do with the transaction being committed.
Chris Lively
How many rows are there in this table (or the linked view). This many reads suggsts a very large mount of data - is that true?
Daniel Renshaw
Without an explicit BEGIN/END TRAN, each insert would be in it's own implicit transaction so there should't be any difference betwen the three.
Daniel Renshaw
4th insert ran fine - stats added above. There is nothing in this table to start with - but yes there are ~800k rows in the dbo.yaf_vaccess view. I guess I never connected that the one table was using the other.
Chris
A: 

The issue is probably caused by the index on the view vaccess_group. Because the view has no padding, adding records will require SQL Server to split the index frequently and it may be that after every third index it fees that an index rebuild is the most optimal way t maintain the index structure/performance.

Try adding some padding to the index. See http://msdn.microsoft.com/en-us/library/ms188783.aspx for info.

CREATE UNIQUE CLUSTERED INDEX [yaf_vaccess_group_UserForum_PK] ON [dbo].[yaf_vaccess_group]
( 
    [UserID] ASC, 
    [ForumID] ASC, 
    [AccessMaskID] ASC, 
    [GroupID] ASC
)
WITH
(
    PAD_INDEX = ON,  -- CHANGE HERE
    FILLFACTOR = 50, -- AND HERE
    STATISTICS_NORECOMPUTE = OFF,
    SORT_IN_TEMPDB = OFF,
    IGNORE_DUP_KEY = OFF,
    DROP_EXISTING = OFF,
    ONLINE = OFF,
    ALLOW_ROW_LOCKS = ON,
    ALLOW_PAGE_LOCKS = ON
)
ON [PRIMARY]

BTW, the reason I failed to spot this index in the YAF database build scripts is because, annoyingly, it's not in indexes.sql. For some reason they've put all view indexes into constraints.sql instead!

Daniel Renshaw
Wow, cant believe you went to that length to help me out. I'll post back with the results later. Thank you so much!
Chris