Author Archives: Robert Haken

About Robert Haken

Software Architect, Founder at HAVIT, Microsoft MVP - ASP.NET/IIS

SQL Query Store: Compare queries in two periods (execution counts, duration)

If you work with Azure SQL or Microsoft SQL Server 2016+, one of the new features there is the Query Store. It stores useful statistics on queries executed, their execution plans, etc. etc.

One of the scenarios you might find useful is the ability to compare queries executed within two periods:

DECLARE @Period1Start datetime, @Period1End datetime, @Period2Start datetime, @Period2End datetime

SET @Period1Start = '20171212 00:00'
SET @Period1End = '20171213 00:00'
SET @Period2Start = '20171214 00:00'
SET @Period2End = '20171215 00:00'

;WITH period1 AS
		AVG(avg_duration) AS avg_duration,
		SUM(count_executions) AS count_executions_total
	FROM sys.query_store_runtime_stats
		INNER JOIN  sys.query_store_runtime_stats_interval ON (query_store_runtime_stats_interval.runtime_stats_interval_id = query_store_runtime_stats.runtime_stats_interval_id)
		INNER JOIN sys.query_store_plan ON query_store_plan.plan_id = query_store_runtime_stats.plan_id
		(sys.query_store_runtime_stats_interval.start_time >= @Period1Start)
		AND (sys.query_store_runtime_stats_interval.end_time <= @Period1End)
	GROUP BY query_id
period2 AS
		AVG(avg_duration) AS avg_duration,
		SUM(count_executions) AS count_executions_total
	FROM sys.query_store_runtime_stats
		INNER JOIN  sys.query_store_runtime_stats_interval ON (query_store_runtime_stats_interval.runtime_stats_interval_id = query_store_runtime_stats.runtime_stats_interval_id)
		INNER JOIN sys.query_store_plan ON query_store_plan.plan_id = query_store_runtime_stats.plan_id
		(sys.query_store_runtime_stats_interval.start_time >= @Period2Start)
		AND (sys.query_store_runtime_stats_interval.end_time <= @Period2End)
	GROUP BY query_id
		period1.avg_duration AS period1_avg_duration,
		period2.avg_duration AS period2_avg_duration,
		CASE WHEN period1.count_executions_total IS NOT NULL THEN (period2.avg_duration - period1.avg_duration) * 100.0 / period1.avg_duration ELSE NULL END AS avg_duration_increase_percent,
		period1.count_executions_total AS period1_count_executions_total,
		period2.count_executions_total AS period2_count_executions_total,
		CASE WHEN period1.count_executions_total IS NOT NULL THEN (period2.count_executions_total - period1.count_executions_total) * 100.0 / period1.count_executions_total ELSE NULL END AS count_execution_increase_percent,
	FROM period2
		LEFT JOIN period1 ON period1.query_id = period2.query_id
		LEFT JOIN sys.query_store_query ON query_store_query.query_id = period2.query_id
		LEFT JOIN sys.query_store_query_text ON query_store_query_text.query_text_id = query_store_query.query_text_id
	--ORDER BY period2.count_executions_total DESC
	ORDER BY count_execution_increase_percent DESC
	--ORDER BY avg_duration_increase_percent DESC


Quartz.NET, Castle Windsor – LifeStyle Per Job (Scoped)

If you have ever tried to use Quartz.NET (a famous job-scheduling library) with Castle Windsor (IoC/DI container) you might need to register a component whose life-style should be bound to the job itself (LifestylePerJob). There are plenty of alternatives available which all have the same characteristics – they do not work:

  • LifestylePerThread – does not reset the thread when running a new job
  • BoundTo<Job>() – does not support typed factories when resolved inside the job
  • BoundTo<object>() – does not support typed factories when resolved inside the job
  • Quartz.IJobFactory + LifestyleScoped – does not support typed factories when resolved into the job (the scope from JobFactory is not propagated inside the job!)

There is a “simple” workaround for such scenarios. You can use LifestyleScoped but you have to begin/end the scope in the job.

If you use the job itself just as a plumbing class where the work itself is encapsulated in a separate service (and you should do this) then you can simply inject both a service-factory and the kernel and then do the scope-work in the job itself:

public class MyJob : IJob
    private readonly IServiceFactory<MyService> myServiceFactory;
    private readonly IKernel kernel;

    public MyJob(IServiceFactory<MyService> myServiceFactory, IKernel kernel)
        this.myServiceFactory = myServiceFactory;
        this.kernel = kernel;

    public void Execute()
        using (var scope = kernel.BeginScope())
            // use your way to work with factories ;-)
            using (var myService = myServiceFactory.Create())
            // BTW: we have an extension method
            myServiceFactory.ExecuteAction(service => service.DoWork());

…the MyService class has all the dependencies you need and as you use it using the factory it behaves as the pseudo-resolution-root for this scenario. You might use the kernel.Resolve+Release in the job but I always prefer not to… ;-)


Tip: Microsoft LogParser [Studio] superfast SQL-like querying of any log file

LogParser (download) is a command line tool from Microsoft which allows you to query any text-based log file using SQL-like syntax. The basic list of supported formats is quite impressive: IISW3C, NCSA, IIS, IISODBC, BIN, IISMSID, HTTPERR, URLSCAN, CSV, TSV, W3C, XML, EVT, ETW, NETMON, REG, ADS, TEXTLINE, TEXTWORD, FS and COM.

I usually use it for querying IIS Log files and believe me it is super-fast. On my Lenovo X1 i7/16GB/SSD it was able to query 8.97GB of log files 2min 12sec!

    TO_INT(COALESCE(EXTRACT_VALUE(cs-uri-query, 'id'), EXTRACT_VALUE(cs-uri-query, 'SouborSablonyID'))) AS SouborID,
    COUNT(*) AS Total
WHERE (cs-uri-stem = '/business/sablony/soubor-partner.aspx') OR (cs-uri-stem = '/business/sablony/soubor.aspx')
GROUP BY Date, SouborID

Output to database

It is not only able to query the logs but you can use it to push the results to SQL database and many other supported data-sources (CSV, XML, …), e.g.

C:\Program Files (x86)\Log Parser 2.2>logparser “SELECT * INTO iisLogs FROM c:\temp\logs\*.log ” -i:iisw3c -o:SQL -server:localhost -database:MyLogs -username:sa -password:sa -createTable: ON

Note: If you want a plain import of log to DB (without any filtering, projection or aggregation) consider using Import Flat File… wizard from SQL Management Studio for better performance. If you want to use LogParser for feeding your DB, check the transactionRowCount option to batch uploaded rows into single transcation (e.g. -transactionRowCount:-1)

Is there any GUI for LogParser?

LogParser itself has always been a command-line utility. As an alternative it has a COM API which allows you to use it from your application. This API has been used to produce several GUIs which make the use of LogParser much easier:

  • Microsoft LogParser Studio (download) is a Microsoft product which brings not only the GUI itself but is shipped with many (181) pre-defined query templates for different log types.
  • Log Parser Lizard GUI is another free tool (with a paid Pro edition) produced outside Microsoft which might be even more powerful. I haven’t tested it yet but it looks promising for those of you who need to play with the logs on daily basis.


You might find following links useful when starting to play with LogParser:

Conclusion to my #NoResharper challenge with Visual Studio 2017

With Visual Studio 2017 being released earlier this year I decided to go for my regular #NoResharper challenge. With every single major version of VS I try to use it without Resharper to find the best setup for me. In general I like the coding productivity boosts Resharper gives me but I hate the way it takes over basic VS features completely and the performance & stability drop it brings. Therefore I regularly try to find a light-weight alternative to R# by using plain VS with only a few reliable extensions.

In the past I used to use Resharper heavily – it was definitely a “must-have” with Visual Studio .NET and Visual Studio 2003. The VS 2005 came with refactorings and I was satisfied working without Resharper till VS2013 when I gave R# another try. There were so many useful productivity boosts not covered by Visual Studio itself or any other stable and light-weight extension (unbeatable T-navigation, Go to definition, Introduce and initialize a field from constructor parameter, Adjust namespaces, etc.). R# returned to my box to better support modern development techniques (IoC/DI, unit-testing, …).

With Visual Studio 2017, it’s improved T-navigation (Go to…), with the help of Roslyn-based refactorings (e.g. Roslynator) and continual updates with new productivity improvements I decided to go without Resharper and after 10 months I can confirm I’m still happy with this decision.

My current Visual Studio setup consists of:

When I check this list of extensions it really seems I might be able to live with plain VS without any major pain! The biggest surprise for me came when I was gathering these items from VS and realized that the Roslynator extension is disabled. (I disabled it after installing the VS2017 15.3 update to test the new Refactorings, Code Generation and Quick Actions.)

UPDATE: If you miss CamelHumps, you might give the Subword Navigation extension a go.




SQL: Padding numbers with leading zeros (15 -> 00015)

You might find a better way, but how about:

= REPLACE(STR(15, 5, 0), ' ', '0')

STR(num, length, decimals) function converts the number to string of given length (padded with spaces) and given number of decimals.


= RIGHT('00000' + @number, 5)

Remember you should handle the formatting in presentation layer, but sometimes you might find this useful…

WinDbg: SOSEX Help – Command Reference

SOSEX is one of the few existing Windows Debugger extensions for managed code (.NET). It adds a few useful commands to the basic SOS, but its command reference is not easy to find online.
The list of its commands is available via ! command. You might find the resulting list useful when considering this extension for your debugging scenario:

0:000> !
SOSEX - Copyright 2007-2015 by Steve Johnson -
To report bugs or offer feedback about SOSEX, please email
Quick Ref:
bhi       [filename]                                     BuildHeapIndex - Builds an index file for heap objects.
bpsc      (Deprecated.  Use !mbp instead)
chi                                                      ClearHeapIndex - Frees all resources used by the heap index and removes it from memory.
dlk       [-d]                                           Displays deadlocks between SyncBlocks and/or ReaderWriterLocks
dumpfd    <FieldAddr>                                    Dumps the properties of a FieldDef structure
dumpgen   <GenNum> [-free] [-stat] [-type <TYPE_NAME>]   Dumps the contents of the specified generation
                   [-nostrings] [-live] [-dead] [-short]
finq      [GenNum] [-stat]                               Displays objects in the finalization queue
frq       [-stat]                                        Displays objects in the Freachable queue
gcgen     <ObjectAddr>                                   Displays the GC generation of the specified object
gch       [HandleType]... [-stat]                        Lists all GCHandles, optionally filtered by specified handle types
help      [CommandName]                                  Display this screen or details about the specified command
lhi       [filename]                                     LoadHeapIndex - load the heap index into memory.
mbc       <SOSEX breakpoint ID | *>                      Clears the specified or all managed breakpoints
mbd       <SOSEX breakpoint ID | *>                      Disables the specified or all managed breakpoints
mbe       <SOSEX breakpoint ID | *>                      Enables the specified or all managed breakpoints
mbl       [SOSEX breakpoint ID]                          Prints the specified or all managed breakpoints
mbm       <Type/MethodFilter> [ILOffset] [Options]       Sets a managed breakpoint on methods matching the specified filter
mbp       <SourceFile> <nLineNum> [ColNum] [Options]     Sets a managed breakpoint at the specified source code location
mdso      [Options]                                      Dumps object references on the stack and in CPU registers in the current context
mdt       [TypeName | VarName | MT] [ADDR] [Options]     Displays the fields of an object or type, optionally recursively
mdv       [nFrameNum]                                    Displays arguments and locals for a managed frame
mfrag     [-stat] [-mt:<MT>]                             Reports free blocks, the type of object following the free block, and fragmentation statistics
mframe    [nFrameNum]                                    Displays or sets the current managed frame for the !mdt and !mdv commands
mgu       // TODO: Document
mk        [FrameCount] [-l] [-p] [-a]                    Prints a stack trace of managed and unmanaged frames
mln       [expression]                                   Displays the type of managed data located at the specified address or the current instruction pointer
mlocks    [-d]                                           Lists all managed lock objects and CriticalSections and their owning threads
mroot     <ObjectAddr> [-all]                            Displays GC roots for the specified object
mt        (no parameters)                                Steps into the managed method at the current position
mu        [address] [-s] [-il] [-n]                      Displays a disassembly around the current instruction with interleaved source, IL and asm code
muf       [MD Address | Code Address] [-s] [-il] [-n]    Displays a disassembly with interleaved source, IL and asm code
mwaits    [-d | LockAddr]                                Lists all waiting threads and, if known, the locks they are waiting on
mx        <Filter String>                                Displays managed type/field/method names matching the specified filter string
rcw       [Object or SyncBlock Addr]                     Displays Runtime Callable Wrapper (RCW) COM interop data.
refs      <ObjectAddr> [-target|-source]                 Displays all references from and to the specified object
rwlock    [ObjectAddr | -d]                              Displays all RWLocks or, if provided a RWLock address, details of the specified lock
sosexhelp [CommandName]                                  Display this screen or details about the specified command
strings   [ModuleAddress] [Options]                      Search the managed heap or a module for strings matching the specified criteria

ListGcHandles - See gch

Use !help <command> or !sosexhelp <command> for more details about each command.
You can also use the /? (or -?) option on any command to get help for that command.