I assume that you are measuring the complete time from select to the
last fetch? There shouldn't be anything that slows the actual query
down, so first measure from before execute to after the first fetch.
I would expect that to be around 5-6 seconds.
The part that will be slow using Python is converting the results to
Python objects. tsql and QA only have to print the results on the
screen so they can ask SQL Server for the results in text. The best
thing you can do is cut the number of result columns down to just
those you need (unless you're building a generic utility of course).
To test this, try selecting just the primary key and time that.
Some data types like datetime and decimal (unfortunately) are going to
take more time than others to convert. If you have a lot of them, you
could cast them to strings. (Unfortunately ODBC drivers, including
SQL Server's, are very buggy when dealing with decimals so I have to
select those as text and convert them myself instead of using the
binary structure.)
That's all I can think of right now, but I'll do some testing.
The performance improvements I was talking about won't affect this --
they were to speed up the actual query if you were using non-NULL
parameters.
Also try testing with pyodbc on Windows if you can to see if there is
a 64-bit or OS difference.