• subscribe
February 19, 2003 12:00 AM

Calculating Concurrent Sessions

When is using cursors the best solution?
SQL Server Pro
InstantDoc ID #37636
Downloads
37636.zip

Solution 4: Cumulative Running Count
The fourth solution, which Listing 8 shows, uses an iterative approach involving a cursor and a loop. The code declares a cursor on a query that returns event types similar to the ones I used in the previous solution, sorted by application and event timestamp. The code forms a loop that iterates through all rows returned by the query I declared in the cursor. In each iteration, the code increments a counter called @concurrent when the current record contains a start event and decrements it when the current record contains an end event. I used 1 and -1 as event types, but you can choose other symbols—such as S and E—to help you distinguish between start and end events. You just have to examine the event type to determine whether to increment or decrement the counter instead of simply adding the event type to it.

A variable called @mx holds the maximum number of concurrent sessions the code has counted in the loop for the application so far. If @concurrent is greater than @mx, @mx receives the current value in @concurrent. When the application in the current record is different than the previous one, the code writes a row to a table variable called @AppsMx, which contains the previous application name (@prevapp) and maximum concurrent sessions (@mx).

About Performance
To test the performance of the different solutions, I populated the Sessions table with 16,000 rows by running the following code:

INSERT INTO Sessions(app, usr, 
  host, starttime, endtime)
  SELECT app, usr, host, 
    starttime+n, endtime+n
  FROM Sessions JOIN Nums
    ON n <= 999

Note that to test the first solution, you also need to populate the Nums auxiliary table with enough rows for 1000 days (60*24*1000).

I tested various index combinations, but all the set-based solutions ran for such a long time, I eventually stopped them. The iterative solution ran for only 2 seconds on my laptop. The iterative solution is the only scalable solution that I came up with—the performance degradation of the cursor-based solution is linear as the table grows larger; with the set-based solutions, it's exponential. If you find a set-based solution that beats the iterative one, I'd love to hear about it.



ARTICLE TOOLS

Comments
  • Kate Luxemburg
    9 years ago
    Mar 17, 2003

    Addendum to my previous comment: The max number of session-pairs to test for concurrency, where n is the number of sessions, is (n * n-1)/2 With use of a variable that decrements the max possible concurrency as the number of session-pairs remaining to be examined for concurrency decreases, and a variable that compares the max possible concurrency to the max concurrency found so far, it is possible to declare the max found and break out of the loop in as few as n compares (that is where all sessions are concurrent).

  • Kate Luxemburg
    9 years ago
    Mar 17, 2003

    Correction to addendum: The min number of session-pair compares is n-1, not n. (I am working with a laptop keyboard and "skating rink" mouse-equivalent as I enter text in this comment window-- that makes it difficult to edit the comment.)

  • Kate Luxemburg
    9 years ago
    Mar 16, 2003

    The solution is clearly and methodically presented BUT consider that it is overkill to solve the problem by examining all possible minutes in the interval for concurrency, given that limit of concurrency is the total number of sessions in the interval for the app-- that is, the limit is reached if there exists any one second in which all the sessions are "on." Order the sessions for each app by start time and number them sequentially. In a table with more than one app, the primary key would be appName + seqNo. For each app, session 1 start < session 2 start < session 3 start ad fin. Examine session pairs for concurrency rather than timeslices. Session 2 is concurrent with session 1 if session 2's start time < session 1's end time. Session 3 is concurrent with 1&2 if its start time < the min(end time) of 1&2. Say there are six sessions for a particular app during the interval. The max number of tests necessary to determine max concurrency is 15-- that is, compare 1&2, 1&3, 1&4, 1&5, 1&6, 2&3, 2&4, 2&5, 2&6, 3&4, 3&5, 3&6, 4&5, 4&6, and 5&6. This query generates the set to examine:

    select s.seqNo,c.seqNo,
    s.startTime, c.startTime,
    isnull(s.endTime,getdate()), isnull(c.endTime,getdate())
    from appSessionsInterval s join appSessionsInterval c
    on s.seqno < c.seqno
    order by s.seqNo, c.seqNo

    Then I used a cursor on this set to count concurrency. Send me email if you want the Transact-SQL.

You must log on before posting a comment.

Are you a new visitor? Register Here