0

I have a ProfileAvatars table with 1000 rows that is the parent table for UserProfile table with 16,557,010 rows.

When I add a new picture (without any child record in UserProfile) and I want to delete it, the Delete statement takes 5-12 seconds to complete the delete query.

This is my query:

DELETE FROM ProfileAvatars
WHERE ProfileAvatarId = 10

Here is the execution plan:

enter image description here

Why is my delete statement taking so long? How can I reduce time needed to delete a single row?


Tables definition

ProfileAvatars:

CREATE TABLE [gnr].[ProfileAvatars](
    [ProfileAvatarId] [int] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,
    [AvatarPictuerPath] [varchar](250) NOT NULL,
    [Description] [nvarchar](250) NULL,
    [CreateBy] [nvarchar](200) NOT NULL,
    [RecordVersion] [timestamp] NOT NULL,
    [CreatedDateUTC] [datetime] NOT NULL,
    [UpdatedDateUTC] [datetime] NULL,
 CONSTRAINT [PK_ProfileAvatars] PRIMARY KEY CLUSTERED 
(
    [ProfileAvatarId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

UserProfile:

CREATE TABLE [sqr].[UserProfile](
    [ProfileId] [bigint] IDENTITY(1,1) NOT NULL,
    [UserId] [bigint] NOT NULL,
    [ProfileCaption] [nvarchar](150) NULL,
    [ProfileAvatarId] [int] NOT NULL,
    [MediaAgeRangeId] [int] NOT NULL,
    [IsKid] [bit] NOT NULL,
    [IsDefault] [bit] NOT NULL,
    [Active] [bit] NOT NULL,
    [ApplicationId] [int] NOT NULL,
    [CreateBy] [nvarchar](200) NOT NULL,
    [RecordVersion] [timestamp] NOT NULL,
    [CreatedDateUTC] [datetime] NOT NULL,
    [UpdatedDateUTC] [datetime] NULL,
    [DeletedDateUTC] [datetime] NULL,
    [IsDeleted] [bit] NOT NULL,
    [UserTasteInsertionDateUTC] [datetime] NULL,
    [UserTasteStatus] [int] NULL,
    [UserTasteSkipDateUTC] [datetime] NULL,
    [PinCode] [varchar](20) NULL,
    [IsLock] [bit] NOT NULL,
 CONSTRAINT [PK_UserProfile] PRIMARY KEY CLUSTERED 
(
    [ProfileId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [sqr].[UserProfile] ADD  CONSTRAINT [DF_UserProfile_IsDeleted]  DEFAULT ((0)) FOR [IsDeleted]
GO
ALTER TABLE [sqr].[UserProfile] ADD  CONSTRAINT [DF_UserProfile_IsLock]  DEFAULT ((0)) FOR [IsLock]
GO
ALTER TABLE [sqr].[UserProfile]  WITH CHECK ADD  CONSTRAINT [FK_UserProfile_MediaAgeRange] FOREIGN KEY([MediaAgeRangeId])
REFERENCES [gnr].[MediaAgeRange] ([MediaAgeRangeId])
GO
ALTER TABLE [sqr].[UserProfile] CHECK CONSTRAINT [FK_UserProfile_MediaAgeRange]
GO
ALTER TABLE [sqr].[UserProfile]  WITH CHECK ADD  CONSTRAINT [FK_UserProfile_ProfileAvatars] FOREIGN KEY([ProfileAvatarId])
REFERENCES [gnr].[ProfileAvatars] ([ProfileAvatarId])
GO
ALTER TABLE [sqr].[UserProfile] CHECK CONSTRAINT [FK_UserProfile_ProfileAvatars]
GO
7
  • 1
    Questtions about performance require the table and index definitions and please add the actual execution plan paste-the-plan. Also which version select @@version of SQL Server
    – Stu
    Commented Jul 1, 2023 at 8:28
  • 1
    Please show both table definitions, and any indexes you have on them.
    – Dale K
    Commented Jul 1, 2023 at 8:30
  • Is this the full query that you are sharing with us, we will also need the table definitions? Based on the execution plan I can see that you are performing a scan on the UserProfile table which would be impacting your performance due to it having to search through all of the records in a non-efficient/non-indexed way. Commented Jul 1, 2023 at 8:35
  • 5
    It needs to do a scan of the 16 million row table to validate the delete wont leave foreign key orphans you should add an index on that column Commented Jul 1, 2023 at 8:35
  • 3
    You already have a clustered index on the table, you can't create a second on it.
    – Thom A
    Commented Jul 1, 2023 at 8:45

1 Answer 1

2

Try creating a non-clustered index on your UserProfile table CREATE NONCLUSTERED INDEX IX_UserProfile_ProfileAvatarId ON sqr.UserProfile (ProfileAvatarId);

This will change the scan (that is currently in the plan for foreign key validation) into a seek. A scan is more costly due to the query running through the whole table to find what it needs. By adding the index it gives the query an idea of where to look and turns the scan into a seek.

enter image description here

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