今日、私が管理しているSQL Serverの1つで以下のエラーが発生しました。
データベース '%。* ls'のオブジェクト '%。* ls'%。* lsに領域を割り当てることができませんでした。 '%。* ls'ファイルグループがいっぱいです。不要なファイルを削除するか、ファイルグループ内のオブジェクトを削除するか、ファイルグループにファイルを追加するか、ファイルグループ内の既存のファイルに対して自動拡張をオンに設定して、ディスク領域を作成します。
Index Reorgの操作中に発生しました。調査の結果、DBが3つのファイルグループに分割され、複数のファイルが含まれていることがわかりました。それらのすべてに、自動拡張が有効になっているファイルが少なくとも1つあり、それらをホストしているディスクに十分な空き容量がありました。それでは、なぜ私のインデックスのメンテナンスが失敗したのですか?私の調査により、このMS記事 https://msdn.Microsoft.com/en-us/library/aa337441.aspx が表示されました:
インデックスが複数のファイルにある場合、ファイルの1つがいっぱいになると、ALTER INDEX REORGANIZEはエラー1105を返すことがあります。プロセスが行を完全なファイルに移動しようとすると、再編成プロセスはブロックされます。この制限を回避するには、ALTER INDEX REORGANIZEの代わりにALTER INDEX REBUILDを実行するか、満杯のファイルのファイル拡張制限を増やします。
OK。したがって、解決策は、インデックスを再構築して新しいファイルに移動することです。しかし、再編成を続行できるように、同じファイルにインデックスを続けたい場合はどうなりますか?それは可能ですか?また、私のDBオブジェクトがどのファイルにあるかを調べることはできますか?ほとんどのブログには、ファイルグループ内にあるオブジェクトを検索するスクリプトがありますが、そのファイルグループ内のファイルを検索して、手動で拡大して修正できるかどうかを確認したいと考えています。
それらのすべてに、自動拡張が有効になっているファイルが少なくとも1つあり、それらをホストしているディスクに十分な空き領域があります。それで、なぜ私のインデックスのメンテナンスは失敗したのですか?
製品ドキュメントに記載されているとおり
インデックスの再編成と再構築 :(強調を追加)
ALTER INDEX REORGANIZE
ステートメントでは、インデックスを含むデータファイルに使用可能なスペースが必要です。これは、操作により、同じファイルに一時作業ページのみを割り当てることができ、ファイルグループ内の別のファイルは割り当てられないためです。そのため、ファイルグループに利用可能な空きページがある場合でも、ユーザーはエラー1105に遭遇することがあります...
しかし、再編成を続行できるように、同じファイルにインデックスを続けたい場合はどうなりますか?それは可能ですか?
はい、必要なスペースが事前に存在すること、または拡張する必要のあるファイルが存在できることを確認する必要があります。
また、私のDBオブジェクトがどのファイルにあるかを調べることはできますか?
これは予想されるほど簡単ではありません。ファイルレベルに正確に到達するには、文書化されていないsys.dm_db_database_page_allocations(SQL Server 2012+)またはDBCC IND
を使用する必要があります。
これを行うcorrectクエリは、このデータベース管理者にありますQ&A:
再構築は必ずしもインデックスを新しいファイルに移動するわけではなく、本質的にインデックスを削除して再作成します。また、比例フィルラウンドロビンアルゴリズムに従ってファイルグループ内のファイル全体に分散されます。成長し、それを行うことができます。
REORGを実行する場合は、スペースが少ないファイルを手動で拡張してREORGを実行します。
テーブルにデータがあるファイルを確認するには、このクエリを使用できます(コードは https://stackoverflow.com/questions/20129001/see-what-data-is-in-what-sql -server-data-file ):
select
OBJECT_NAME(p.object_id) as my_table_name,
u.type_desc,
f.file_id,
f.name,
f.physical_name,
f.size,
f.max_size,
f.growth,
u.total_pages,
u.used_pages,
u.data_pages,
p.partition_id,
p.rows
from sys.allocation_units u
join sys.database_files f on u.data_space_id = f.data_space_id
join sys.partitions p on u.container_id = p.hobt_id
where
u.type in (1, 3) and
OBJECT_NAME(p.object_id) = '<your table name>'
GO