In the past we have produced several popular articles explaining how to cleanup and fix Windows Server Update Services (WSUS):

However, last week ran into a problem with one client whose WSUS was so burdened by unnecessary patches the WSUS native tools (including the command line tools) had taken over a week to run and we still had no idea how long it was going to take to complete.

By “unnecessary patches” we mean that whoever setup the WSUS selected all PRODUCTS and all CLASSIFICATIONS.  We made the appropriate corrections and got it down to the dozen or so PRODUCTS we cared about, but now we had to delete the garbage to get WSUS fully functional.

In our case the database was running on a full SQL server which was different from where WSUS had been installed.  We RDP’d to the SQL server and ran the following cleanup commands (all of which we took verbatim from various Microsoft articles) right in SQL MANAGEMENT STUDIO:


1 – Create Special WSUS Indexes So the Next Queries Run Fast

Download this script to create special indexes for WSUS Database HERE

Create Special WSUS Indexes So the Next Queries Run Faster

If the indexes were already created, then you will get an error (which you can safely ignore) like :

Msg 1913, Level 16, State 1, Line 4
The operation failed because an index or statistics with name ‘nclLocalizedPropertyID’ already exists on table ‘dbo.tbLocalizedPropertyForRevision’.


2 – Force a Reindexing of the Entire WSUS Database

Download this script to reindex WSUS database HERE.

On my clients server this took more than an hour to complete.  I got very worried when the MESSAGES tab (SQL Management Studio) did not add anything for about 30 minutes, but I could see SQL was still grinding my CPU in Task Manager

Force a Reindexing of the Entire WSUS Database in SQL

For more details on this script see THIS Microsoft article


3 – Find Out How Many Patches Are Superseded:

This query just takes a few seconds because it is just a count:

Select COUNT(UpdateID) from vwMinimalUpdate where IsSuperseded=1 and Declined=0

You might also find it interesting to check the FREE SPACE on the database by:

  1. Launch SQL SERVER MANAGEMENT STUDIO on the SQL SERVER
  2. Expand DATABASES
  3. Right click on the SUSDB and see what FREE SPACE is

4 – SQL Command To Delete Updates From WSUS SUSDB Database

Download this SQL Command To Delete Updates From WSUS SUSDB Database HERE but read the notes under this screenshot BEFORE you run it.

SQL Command To Delete Updates From WSUS SUSDB Database

There are three things (as far as we have figured out!) you need to know about this script before running it:

  1. Make sure you have created and updated the WSUS indexes as noted in steps 1 and 2 above
    • Those indexes will allow this script to delete the junked updates at a rate of about 1 update for every 2 seconds but if you haven’t got those indexes setup it will take about 1 minute per update… not good.
  2. The script will almost certainly need to be run multiple times until all the old patches are deleted
    • In this case we have it set to 250 which means it takes about 5 minutes per execution
    • If we had 10,000 patches to delete it that means we would need to run the query 40 times
  3. Change the number at the end of the line “IF @curitem < 250” to change the number of updates this script will delete each time you run it
    • ONE OF OUR READERS SUGGESTED THIS LINE:
      if you are confident you wont crash your server, update “IF @curitem < 250″ to “IF @curitem < @totaltodelete +1”
    • We suggest you start by setting that number to just 10 for your first round, because if your indexes are not setup (see steps 1 and 2 above) then it will take about 10 minutes to complete and you will be sad
    • After you run it at 10, and find that it takes about 15 seconds to run, you may want to change the number to 250 for your next run, and then to 2000 after you are comfortable you are not pinning out your server

Rerun that SQL query over and over until it returns 0 ROWS AFFECTED.


5 – Wrap up!

At this point you are mostly done but there are some small things left to wax the job.

5A – Script to Clean Up WSUS

Now that you have SQL cleaned up you can download the Decline-SupersededUpdatesWithExclusionPeriod.ps1 powershell WSUS cleanup command right HERE

NOTE – Rename the file to end with .PS1 extension and then run it in a PowerShell command line as an Administrator

This command took about 10 minutes to run on my servers and it got slower as the it got closer to finishing.

Decline-SupersededUpdatesWithExclusionPeriod.ps1 -UpdateServer SERVERNAME -Port 8530

Decline-SupersededUpdatesWithExclusionPeriod script outputIn my case I reduced the number of updates to just 8400 from 40000.

5B – Rerun Step 2 Again To Get That Index Current

Just what it says.  Run it again; it will be fast.

5C – Check to See How Many Old Updates Still Remain

At this point you can go back to step 3 and see how many old updates still exist in the database.  It should be zero.

You might also find it interesting to check the FREE SPACE on the database by:

  1. Launch SQL SERVER MANAGEMENT STUDIO on the SQL SERVER
  2. Expand DATABASES
  3. Right click on the SUSDB and see what FREE SPACE is

In my case after nearly a week of trying to clean the database using the normal scripts and the SERVER CLEAN UP WIZARD, the SUSDB changed from 200MB free to 425MB free.  After running the above scripts (just two hours of work) the SUSDB changed from having 425MB free to 4500MB free.

how much free space in WSUS database after cleanup

After I ran through the next two items, I checked the SPACE AVAILABLE again, and found it was now at 6600MB.  That is an impressive amount of space to get back on a SQL database.

5D – Run the WSUS SERVER CLEAN UP WIZARD

Microsoft recommends you finish off all these scripts with a final coat of wax by running the  WSUS SERVER CLEAN UP WIZARD (UNDER OPTIONS at the bottom of the left side menu, in WSUS).  It won’t be instant but it will move and should finish within 10 minutes.  The one in this screenshot took 4 minutes to complete and you can see the massive 92GB of disk space I got back!

WSUS server cleanup wizard result

5E – Niceties

Now that your WSUS is functional again, it is a good time to manually DECLINE junk that you office is never going to use.  For instance, my offices have no ARM64 devices, so I search in the WSUS interface, I do a search (to right) for text that contains ARM64, then I select all of them and decline them.  I do the same thing for:

  • OFFICE XP
  • Windows XP
  • Windows Vista
  • Windows Embedded Standard 7
  • Media Center
  • Exchange Server 2003
  • Exchange Server 2010
  • Itanium (in case you are wondering Itanium is an old CPU technology)
  • and any other ancient or junk apps you notice

Once that is done I run the WSUS cleanup wizard again to unload that junk before it clogs up my system again.



7 Comments

luper · May 26, 2023 at 12:29 am

Hi

thanks for your script
maybe this can be useful for someone who want use sync drivers in his WSUS
mine was constantly crashing during the spCompressUpdate phase due to the insane number of revision for each driver.
after looking the database, I’ve found around 200k updates for 3+M revisions
I have altered your script from section 4 to do it with the revisions. it took me around 8 hours to complete but the console is working fine now

here the code

USE SUSDB
DECLARE @var1 INT, @curitem INT, @totaltodelete INT
DECLARE @msg nvarchar(200)
CREATE TABLE #results (Col1 INT) INSERT INTO #results(Col1)
EXEC spGetUpdatesToCompress
SET @totaltodelete = (SELECT COUNT(*) FROM #results)
SELECT @curitem=1
DECLARE WC Cursor FOR SELECT Col1 FROM #results
OPEN WC
FETCH NEXT FROM WC INTO @var1 WHILE (@@FETCH_STATUS > -1)
BEGIN SET @msg = cast(@curitem as varchar(5)) + ‘/’ + cast(@totaltodelete as varchar(5)) + ‘: Deleting ‘ + CONVERT(varchar(10), @var1) + ‘ ‘ + cast(getdate() as varchar(30))
RAISERROR(@msg,0,1) WITH NOWAIT
EXEC spCompressUpdate @localUpdateID=@var1
SET @curitem = @curitem +1
IF @curitem < 250
FETCH NEXT FROM WC INTO @var1
END
CLOSE WC
DEALLOCATE WC
DROP TABLE #results

hoping it can help some people 🙂

    Jeff · September 13, 2023 at 3:52 pm

    what is ‘3+M’ ?

Ryan · March 9, 2023 at 3:12 pm

Suggestion for section 4 – if you are confident you wont crash your server, update “IF @curitem < 250" to "IF @curitem < @totaltodelete +1"

    Ryan · March 9, 2023 at 3:14 pm

    Better yet – “IF @curitem <= @totaltodelete"

    Ian Matthews · March 13, 2023 at 10:33 pm

    Hi Ryan;

    Thanks, I added that line right into section 4.3 🙂

Understanding the Algorithms and Tech Behind Effective Odds Calculators – Up & Running Technologies, Tech How To's · September 6, 2023 at 6:49 pm

[…] calculators use robust backend technologies like SQL databases for data storage and Python or Java for computational […]

SOLVED: WSUS Stuck On RESET SERVER NODE – Up & Running Technologies, Tech How To's · November 2, 2022 at 9:41 am

[…] addition to running the WSUS SERVER CLEAN UP WIZZARD and scripts that clean up the WSUS SQL database, the more common fix is to adjust the Application Pool settings in […]

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *