処理される前にWebアプリケーションからアップロードされたデータを一時的に保持する2つのテーブルがあります。これは、Azure SQLデータベースで実行されています。
_Id uniqueidentifier
CustomerId uniqueidentifier
FileName nvarchar(MAX) NULL
UploadDate datetime
UploadedBy nvarchar(MAX) NULL
_
_Id uniqueidentifier
Data varbinary(MAX) NULL
UploadFileId uniqueidentifier
[Index] int
_
UploadFile
には、UploadFileChunk
へのカスケード削除を伴う外部キーがあります。 UploadFileChunk
はUploadFileId
に非クラスター化インデックスを持っています。それぞれ1MBのチャンクをアップロードしています。
このデータの挿入と読み取りは非常にうまく機能していますが、データが処理された後にUploadFile
からレコードを削除すると、本当に遅くなります。 S0 10 DTUテストのAzure環境では、子のチャンクが500個以下の12個のレコードをまとめて削除するのに38分かかりました(例に過ぎません。高出力の本番環境と高速のローカルマシンではパフォーマンスが低下します)。
どうすれば速くできますか?
_UploadFileChunk.FileUploadId
_のインデックスがです。これが 実行計画 です。
次のクエリを実行しました( [SQL Azureでのブロッククエリの検索 から))。スローデリートは途中で行われ、結果は返されませんでした。
_SELECT TOP 10
r.session_id,
r.plan_handle,
r.sql_handle,
r.request_id,
r.start_time,
r.status,
r.command,
r.database_id,
r.user_id,
r.wait_type,
r.wait_time,
r.last_wait_type,
r.wait_resource,
r.total_elapsed_time,
r.cpu_time,
r.transaction_isolation_level,
r.row_count,
st.text
FROM sys.dm_exec_requests r
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) AS st
WHERE
r.blocking_session_id = 0
AND r.session_id IN
(
SELECT DISTINCT (blocking_session_id) FROM sys.dm_exec_requests)
GROUP BY
r.session_id,
r.plan_handle,
r.sql_handle,
r.request_id,
r.start_time,
r.status,
r.command,
r.database_id,
r.user_id,
r.wait_type,
r.wait_time,
r.last_wait_type,
r.wait_resource,
r.total_elapsed_time,
r.cpu_time,
r.transaction_isolation_level,
r.row_count,
st.text
ORDER BY
r.total_elapsed_time DESC;
_
切り捨ては[削除するより]速いかもしれませんが、これらの2つのテーブルには複数のファイルのデータが含まれているため、一度に1つずつ削除できる必要があります。 nvarchar(max)
列はおそらく別のものになる可能性があります。これは、ドメインクラスに基づいてEntity Frameworkが生成したものにすぎません。それがこの問題に役立つと思いますか?
FileUploadChunks
から直接レコードを削除するのと同じくらい遅いことを確認しました。私の非常に遅い例(S0 10 DTU)では、削除された行ごとに約1秒です。
Microsoftのゴールドパートナーサポートとの1週間のやり取りを終えたところです。彼らは、この状況は改善されておらず、これらの遅い削除はSQL Azure/2016の通常の動作であることを確認しています。