ASP.NET Universal ProviderをSQL的側面から見てみた
「ASP.NET Univarsal Providers のセッションプロバイダを使ってみる」で、次のような紹介がありました。
ASP.NET Univarsal Providersのセッションプロバイダって、セッションの破棄もしてくれるの?という話題から。結論から言うと、「期限切れのセッションは削除してくれます。但しパフォーマンスに問題がありそうなやり方で。」となります。
定期ジョブを処理する機能SQL Server Agentが提供されていないSQL Aureへの対応としては仕方ないと思います。とは言え、アクセスの度に何をしているのかを調べてみようと思います。
毎回アクセス時にしていること(SQL的にね)
アクセスした時間に、セッション有効時間切れしてるものがあるかどうかを確認します。
SELECT
[Extent1].[SessionId] AS [SessionId],
[Extent1].[Created] AS [Created],
[Extent1].[Expires] AS [Expires],
[Extent1].[LockDate] AS [LockDate],
[Extent1].[LockCookie] AS [LockCookie],
[Extent1].[Locked] AS [Locked],
[Extent1].[SessionItem] AS [SessionItem],
[Extent1].[Flags] AS [Flags],
[Extent1].[Timeout] AS [Timeout]
FROM [dbo].[Sessions] AS [Extent1]
WHERE [Extent1].[Expires] < @now’@now datetime2(7) 2011-08-07 06:38:04.1649431
期限切れのセッションがあれば、セッション情報を削除します。
delete [dbo].[Sessions]
where ([SessionId] = @0)
自分のセッション情報を取得します。
SELECT
[Limit1].[SessionId] AS [SessionId],
[Limit1].[Created] AS [Created],
[Limit1].[Expires] AS [Expires],
[Limit1].[LockDate] AS [LockDate],
[Limit1].[LockCookie] AS [LockCookie],
[Limit1].[Locked] AS [Locked],
[Limit1].[SessionItem] AS [SessionItem],
[Limit1].[Flags] AS [Flags],
[Limit1].[Timeout] AS [Timeout]
FROM ( SELECT TOP (1)
[Extent1].[SessionId] AS [SessionId],
[Extent1].[Created] AS [Created],
[Extent1].[Expires] AS [Expires],
[Extent1].[LockDate] AS [LockDate],
[Extent1].[LockCookie] AS [LockCookie],
[Extent1].[Locked] AS [Locked],
[Extent1].[SessionItem] AS [SessionItem],
[Extent1].[Flags] AS [Flags],
[Extent1].[Timeout] AS [Timeout]
FROM [dbo].[Sessions] AS [Extent1]
WHERE [Extent1].[SessionId] = @id
) AS [Limit1]@id nvarchar(4000) lbw5dkyodyilchsipwuzo5dj/LM/W3SVC/1273337584/ROOT
無かったら、セッション情報を格納します。
insert [dbo].[Sessions]([SessionId], [Created], [Expires], [LockDate], [LockCookie], [Locked], [SessionItem], [Flags], [Timeout])
values (@0, @1, @2, @3, @4, @5, @6, @7, @8)
もっかい自分のセッション情報があるかを確認しセッション情報があれば、セッション情報の有効期限を更新します。
update [dbo].[Sessions]
set [Expires] = @0, [LockDate] = @1, [Locked] = @2
where ([SessionId] = @3)
まとめ
一回のアクセスで、都合8SQL流れているように見えます。アクセスする度に8SQL流れ、アクセスの都度セッションの有効期限を更新しています。
SessionテーブルのExpiresにインデックスを貼ってないので、アクセスの度にフルスキャンが走るのは間違いありません。しかし、データ量が少ない場合はインデックスが貼ってあっても、インデックスを使用せずにテーブルをフルスキャンします。一方、アクセスする度に有効期限の日付を更新するUpdate文が流れますので、インデックスが貼ってあると更新時のコストが増加します。
どのタイミングでインデックスが貼ってある効果が出るかまでは今回調べてませんが、同時セッション数10~20程度であれば、インデックスが無い方がパフォーマンス上優位だと思います。
同時セッション数が多いシステムで運用する場合には、インデックスを作成するとパフォーマンス改善する可能性があります。