Ok, the non-sql expert in me just inherited a new "problem query" that was causing major load issues and taking quite a while to run. Basically it's a logon usage by interval report, showing the number of employees that logged on in each interval (currently 1 day). When run for small ranges (say up to 90 days or so) it's not too bad. But when pulled for a year's time, it slows to a crawl.
The first thing I noticed was it used cursors, so I took those out and made the following re-write. Currently, the logon and logoff times are not indexed in this table, which is another step I'm looking at, but in the meantime, can anyone suggest any ways that might tweak this up a bit? Removing the cursor took a year long run from 2:04 to about 1:25, but I'd really like to get it lower than that if at all possible.
The first thing I noticed was it used cursors, so I took those out and made the following re-write. Currently, the logon and logoff times are not indexed in this table, which is another step I'm looking at, but in the meantime, can anyone suggest any ways that might tweak this up a bit? Removing the cursor took a year long run from 2:04 to about 1:25, but I'd really like to get it lower than that if at all possible.
Code:
DECLARE @date SMALLDATETIME
DECLARE @enddate SMALLDATETIME
DECLARE @sampleperiod INT
DECLARE @siteid VARCHAR(50)
DECLARE @EmpFilter NVARCHAR(4000)
DECLARE @ShowWeekends BIT
SET @date = '1/1/2006'
SET @enddate = '12/31/2006'
SET @sampleperiod = 24
SET @siteid = 'xyz'
SET @EmpFilter = 'SELECT EmpID FROM Employee'
SET @ShowWeekends = 0
SET NOCOUNT ON
CREATE TABLE #tmpEmps (EmpID INT NOT NULL)
INSERT INTO #tmpEmps EXEC (@EmpFilter)
CREATE TABLE #temp (countdate SMALLDATETIME NULL, usercount INT NULL)
WHILE @date < @enddate
BEGIN
INSERT INTO #temp (countdate) VALUES (@date)
SET @date = DATEADD(hh,@sampleperiod,@date)
END
IF @ShowWeekends = 1
BEGIN
SELECT countdate AS bucket, DATENAME(dw,countdate) AS dayname,
(SELECT COUNT(DISTINCT lh.empid) FROM LogonHistory lh
INNER JOIN #tmpEmps te ON te.empid = lh.empid
WHERE LogonTime BETWEEN countdate AND DATEADD(hh,@sampleperiod,countdate)
OR LogoffTime BETWEEN countdate AND DATEADD(hh,@sampleperiod,countdate) AND siteid = @siteid) AS usercount
FROM #temp d
END
ELSE
BEGIN
SELECT countdate AS bucket, DATENAME(dw,countdate) AS dayname,
(SELECT COUNT(DISTINCT lh.empid) FROM LogonHistory lh
INNER JOIN #tmpEmps te ON te.empid = lh.empid
WHERE LogonTime BETWEEN countdate AND DATEADD(hh,@sampleperiod,countdate)
OR LogoffTime BETWEEN countdate AND DATEADD(hh,@sampleperiod,countdate) AND siteid = @siteid) AS usercount
FROM #temp
WHERE DATENAME(dw,countdate) NOT IN ('Saturday',
'Sunday')
END
DROP TABLE #temp
DROP TABLE #tmpEmps