I'm running a 350GB
database on my PC with ~40 million rows.
SQL Server 2014, Win7, AMD 8350 @ 4.8GHZ, 16 GB of RAM, and a 500 GB
SSD (database is hosted on it's own 500 GB SSD, with a throughput of
500MB/500MB read/write).
The database is not being updated, I'm just analyzing/reading it. With the creation of a few indexes
, any join
, count(*)
etc, takes less than 1 minute, which is ok for my purposes. I have been running some queries (after running a single join query, 40-50 times, it becomes slow) on the data, and now calls that took 1 minute, are still running 20 minutes later.
I keep a careful eye on system resources, and I can see the SSD
kick in when the query starts, it reads for 20-30 seconds, then it reads at 121kB/second
for the next 20 minutes. This is not a CPU problem, or disk problem. I am limited with my amount of RAM, however the calls run fine when I first loaded the database, now, nothing runs, 25 minutes later.
Effectively I cannot query the database anymore, any call takes excessively long even a basic SELECT
statement. I have tried rebuilding the indexes and updating statistics, but no difference.
I don't have a lot of experience on this so it's entirely possible that my SQL query is incorrect, in which case I'd expect an error, or for it to finish executing with 0 results, but neither occurs.
What I am trying to do is count all instances of a 'TypeID', in the 5 seconds prior to a time based on the table ACALLS.
SELECT ACALLS.StartTime, ACALLS.Time, ACALLS.ServerIP, ACALLS.SRVR, ACALLS.calls, ACALLS.TOKEN, COUNT(TypeID) as ExecRate
FROM ACALLS
INNER JOIN MAINVIEW ON
MainView.TimeStamp BETWEEN ACALLS.StartTime and DATEADD(ss,-5,ACALLS.StartTime)
WHERE DATEPART(hour,MainView.TimeStamp) BETWEEN 10 and 13 and
CAST(MainView.TimeStamp as date) = '2015-12-09' and
MainView.TypeID = '123456789'
GROUP BY Acalls.STartTime, ACALLs.TIME, ServerIp,SRVR, ACALLS.CALLS, ACALLS.TOKEN
ORDER BY Acalls.StartTime
Best Answer
You have a non-SARGable query - even if you have good indexes, you're not using them with that query.
First, a knee-jerk reaction to pageiolatch_sh is reading pages from disk into the buffer; you don't have enough RAM for the data it's trying to pull.
Second, you need to look at the execution plan and its use of indexes - or the lack thereof.
Quit using functions in your joins and your WHERE, and only get the data you absolutely need to start with.
"BETWEEN ACALLS.StartTime and DATEADD(ss,-5,ACALLS.StartTime)" - get rid of that DATEADD in the BETWEEN.
WHERE DATEPART(hour,MainView.TimeStamp) BETWEEN 10 and 13 and CAST(MainView.TimeStamp as date) = '2015-12-09'
same thing - get rid of the CAST - change '2015-12-09' to one or two @parameters of the right data type for MainView.TimeStamp >= @StartTimestamp AND MainView.TimeStamp < @EndTimestamp
and get rid of that DATEPART by restricting the @StartTimestamp and @EndTimestamp to include your hours criteria as well.
Perhaps load up a #temp table with just the primary/unique keys of rows that meet those MainView criteria before the join.
Hmm... also, if Mainview is a complex view, go straight to the base tables to load up that #temp table
Don't forget to use Profiler to check and see if adding (compound if need be) indexes on the #temp or other staging table is a net gain or a net loss :).