programming4us
programming4us
DATABASE

Defensive Database Programming with SQL Server: The Ticket-Tracking System (part 2) - Removing the performance hit of ON UPDATE CASCADE

1/17/2011 5:37:17 PM

Removing the performance hit of ON UPDATE CASCADE

We need to discuss in a little more detail the ON UPDATE CASCADE behavior and its performance implications. Whenever a developer's status changes, the corresponding DeveloperStatus column in the Tickets table changes automatically, for all the tickets assigned to that developer. This behavior definitely gets the job done, and our business rules are robustly enforced. However, we need to ask ourselves the following question: why do we need to update the DeveloperStatus column for closed tickets? Clearly our CHECK constraint only needs to use DeveloperStatus if the ticket is open.

Why should we care if the DeveloperStatus column is updated for closed tickets? The reason is simple: performance. In our test cases, with just one or two developers and only one ticket, it does not matter whether or not we update the DeveloperStatus column for closed tickets. However, in real life, a developer might have hundreds or even thousands of closed tickets assigned to him or her, but just a handful of active ones. If we can avoid modifying those closed tickets every time a developer goes on vacation, then we can significantly improve the performance of the system.

Let us change our solution, so that the DeveloperStatus column is not updated for closed tickets. In order to do this, we need to ensure that Tickets.DeveloperStatusNULL for all closed tickets. Since open tickets can never be assigned to a developer on vacation, the result will be that Tickets.DeveloperStatus can now only be Active or NULL, and so the ON UPDATE CASCADE clause becomes redundant. is

Execute the script in Listing 15, which performs the following steps:

  • deletes the contents of both the Tickets and Developers tables (of course, in a production system we would take steps to preserve our data rather than delete it outright)

  • makes the Tickets.DeveloperStatus column nullable, because we need it to be NULL for closed tickets

  • modifies our CHK_Tickets_ValidStatuses constraint to enforce the rules that DeveloperStatus is NULL for all closed tickets, and is Active for all active ones

  • drops the FK_Tickets_Developers_WithStatus constraint and recreates it without the ON UPDATE CASCADE clause, which is now redundant.

Listing 15. Making the DeveloperStatus column nullable and adding a new CHK_Tickets_ValidStatuses constraint to ensure the column is NULL for all closed tickets.

We are now ready to run some tests against our changed implementation. Listing 16 inserts some fresh test data, including a closed ticket with NULL DeveloperStatus.

Listing 16. Repopulating Developers and Tickets tables.

If we rerun Listing 11, it will raise an error, confirming that Justin cannot go on vacation, because there is an active ticket assigned to him

Now, when we close an open ticket, we also need to set DeveloperStatus to NULL, as shown in Listing 17.

Listing 17. Closing the ticket.

At this moment, both tickets assigned to Justin are closed, and DeveloperStatus is NULL for both those tickets. This means that, for these tickets, the pair of columns (AssignedDeveloperID, DeveloperStatus) does not refer to any row in the Developers table, because DeveloperStatus is NULL. Note that, even for closed tickets, we still need to ensure that Tickets.AssignedDeveloperID refers to a valid Developers.DeveloperID; this is why we have another FOREIGN KEY constraint (FK_Tickets_Developers) on AssignedDeveloperID only.

Let's proceed with the testing. If Justin goes on vacation, we expect that no rows in the Tickets table should be modified, as verified by Listing 18.

Listing 18. No rows in the Tickets table are modified if Justin goes on vacation.

If Justin is on vacation we cannot reopen a ticket assigned to him, as verified by Listing 19.

Listing 19. Trying to reopen a ticket assigned to Justin.

We have seen how three constraints work together to enforce a rather complex business rule. Originally, we used an approach that works in the simplest possible way, and then we modified it to be more efficient. We have also removed the side effect of changes in Developers.DeveloperID column propagating into the Tickets table (and our FK constraint will prohibit changes that would result in orphaned rows).

Let's move on to discuss another case where constraints really shine: inventory systems.

Other  
  •  SQL Server 2008 : Working with DML Queries - Using the MERGE Statement
  •  Defensive Database Programming with SQL Server : Client-side Error Handling
  •  SQL Server 2008 : Working with DML Queries - Using the DELETE Statement
  •  Programming Microsoft SQL Server 2005: Using Data Mining Extensions (part 2) - Data Mining Predictions Using DMX
  •  Programming Microsoft SQL Server 2005: Using Data Mining Extensions (part 1) - Data Mining Modeling Using DMX
  •  SQL Server 2008 : Working with DML Queries - Using the UPDATE Statement (part 2)
  •  SQL Server 2008 : Working with DML Queries - Using the UPDATE Statement (part 1)
  •  Azure Programming Considerations
  •  Programming with SQL Azure : Record Navigation in WCF Data Services
  •  Defensive Database Programming with SQL Server : TRY...CATCH Gotchas (part 2) - TRY...CATCH blocks cannot catch all errors
  •  
    video
     
    Video tutorials
    - How To Install Windows 8

    - How To Install Windows Server 2012

    - How To Install Windows Server 2012 On VirtualBox

    - How To Disable Windows 8 Metro UI

    - How To Install Windows Store Apps From Windows 8 Classic Desktop

    - How To Disable Windows Update in Windows 8

    - How To Disable Windows 8 Metro UI

    - How To Add Widgets To Windows 8 Lock Screen

    - How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010
    programming4us programming4us
    programming4us
     
     
    programming4us