Sign in
SQL Server Product Manager チームブログ
マイクロソフト株式会社の SQL Server Product Manager チームのブログです。
Options
Home
Share this
RSS for posts
Atom
RSS for comments
Search Blogs
Tags
Announce
Pages
SQL Fast Track
SQL Server code name "Denali"
SQL Server Reporting Services
Technical
イベント
サポート技術情報
セキュリティ
セミナー
事例紹介
動画
書籍紹介
記事紹介
評価版
Archive
Archives
April 2014
(1)
September 2011
(1)
August 2011
(2)
July 2011
(3)
May 2011
(1)
April 2011
(2)
March 2011
(6)
February 2011
(4)
January 2011
(3)
December 2010
(5)
November 2010
(1)
October 2010
(2)
September 2010
(1)
August 2010
(2)
July 2010
(2)
June 2010
(11)
May 2010
(6)
April 2010
(5)
March 2010
(6)
February 2010
(2)
January 2010
(6)
December 2009
(10)
November 2009
(2)
October 2009
(5)
September 2009
(3)
August 2009
(10)
July 2009
(9)
June 2009
(12)
May 2009
(11)
April 2009
(29)
March 2009
(1)
[Sample] えす!エス!レスキュー SQL Server -どっぷりリファレン中!!- Vol. 1
TechNet Blogs
»
SQL Server Product Manager チームブログ
»
[Sample] えす!エス!レスキュー SQL Server -どっぷりリファレン中!!- Vol. 1
[Sample] えす!エス!レスキュー SQL Server -どっぷりリファレン中!!- Vol. 1
T.Kitagawa
4 Aug 2009 4:40 PM
Comments
0
Likes
◆◇◇◆━━━━━━━━━━━━━━━━━━━━2009.06.10━━━・‥…
えす!エス!レスキュー SQL Server
-どっぷりリファレン中!!-
・‥…━━━━━━━━━━━━━━━━━━━━━Vol. 1━━━━◆◇◇◆
<<目次>>
■SQL Server リファレン中!! その1
■お知らせ・・・○ご質問について
■編集者より
┏─────────────────────────────────┓
┃SQL Server リファレン中!! ┃
┗─────────────────────────────────┛
インサイトテクノロジーがお送りする、
SQL Serverのメルマガ
「えす!エス!レスキュー SQL Server -どっぷりリファレン中!!-」
第1弾をお届けします!!
このメルマガでお送りする情報は以下のエディションをターゲットにし、
記載しております。
ターゲット : SQL Server 2008 Enterprise Edition x86
Enterprise Editionが高い!と思われるかも知れませんが、
180日間限定のトライアル版を、以下のサイトからダウンロードできますので
ぜひ、メルマガを見つつ、色々と試していただけたらと思います。
SQL Server 2008 の評価版ダウンロードページ
http://www.microsoft.com/japan/SQLServer/2008/downloads/default.mspx
このSQLServerのメルマガは、夏椰(かや)がお送りします。
最初なので、簡単に自己紹介をさせてください。
歳は30歳です。(2009年06月現在)
身長は166cm、基礎代謝が1400kcalぐらいです。
ソフトテニスと一眼レフが趣味です。
データベースも趣味だったのですが、
インサイトテクノロジーに入社し、お仕事になりました♪
そして、こうして皆様にメルマガという形で
私の知っていることや、チャレンジしたことをお届けする機会を
得る事が出来、嬉しく思っています。
では、本題へ。
今回のSQL Server - どっぷりリファレン中では、
SQL Serverにおける「データファイル」と「ページ」、「エクステント」について
見ていきます。
======================================================================
アジェンダ
======================================================================
今回のメルマガでは以下の内容をお伝えします。
1) データファイルとページ
2) データベースとデータファイル・ページ
・ ページの種類
・ ページとエクステントの関係
・ テーブルとページの関係
4) データファイルとエクステント
======================================================================
データファイルとページ
======================================================================
SQL ServerでもOracleでも、データはデータファイルに格納されていきます。
そのデータファイルの中身はどうなっているんでしょうか?
まず最初に、接続中のインスタンスが使っている
ファイルの一覧を取得し、表示します。
<< SQL文 >>
/********************************************************************/
SELECT
*
FROM
sys.master_files;
/********************************************************************/
# sys.master_filesについては MSDNライブラリ参照。
#
http://msdn.microsoft.com/ja-jp/library/ms186782.aspx
<< 実行結果(抜粋) >>
/********************************************************************/
database_id file_id type type_desc name
----------- ----------- ---- ---------- ------------------------------
1 1 0 ROWS master
1 2 1 LOG mastlog
2 1 0 ROWS tempdev
2 2 1 LOG templog
3 1 0 ROWS modeldev
3 2 1 LOG modellog
4 1 0 ROWS MSDBData
4 2 1 LOG MSDBLog
5 1 0 ROWS ReportServer
5 2 1 LOG ReportServer_log
6 1 0 ROWS ReportServerTempDB
6 2 1 LOG ReportServerTempDB_log
7 1 0 ROWS test
7 2 1 LOG test_log
/********************************************************************/
# 実行結果
http://www.insight-tec.com/mailmagazine/SQL_ref/sys.master_files.png
/********************************************************************/
この結果を見て分るように、
・行データが入るファイル
・ログデータが入るファイル
の2種類のファイルが存在していることが分るかと思います。
sys.master_filesが出力する列数は多く、様々な情報が入っていますので
ファイルサイズと必要な情報がある程度見えるように、
出力列を絞って、SQLを実行していきます。
また、4つの列に対し、式を入れていきます。
max_size列が-1の場合、
ファイルの最大値は可能サイズまで増加するという"無制限"指定なので、
max_size列が0以下の場合は、"無制限"と表示されるようにしました。
growth列は0の場合、サイズの増減がない固定ファイルサイズになりますので
その場合には、"固定"と表示されるようにしました。
そして、growth列の値はis_percent_growthの値が1の場合はパーセント(%)、
それ以外はページ数を示していますので、
is_percent_growth列の値を見て、growthの増え方がどちらなのか、
"%"と"page(s)"という"単位"を付加して表示するようにしました。
DB_NAMEという関数を使い、
database_idに対応するデータベースの名前が表示されるようにしました。
# MSDN
http://msdn.microsoft.com/ja-jp/library/ms189753.aspx
それでは、組みあがったSQL文と実行結果を記載します。
<< SQL文 >>
/********************************************************************/
SELECT
DB_NAME(database_id) dbname,
name,
file_id,
file_guid,
physical_name,
size,
case when max_size < 0 then N'無制限' else
CAST(max_size as nvarchar) end max_size,
case when growth = 0 then N'固定' else
CAST(growth as nvarchar) end +
case when is_percent_growth = 1 then N'%' else
N'page(s)' end growth
FROM
sys.master_files
;
/********************************************************************/
<< 実行結果(抜粋) >>
/********************************************************************/
dbname physical_name
------ ------------------------------------------------------------
master C:\SQL ServerData\MSSQL10.MSSQL Server\MSSQL\DATA\master.mdf
master C:\SQL ServerData\MSSQL10.MSSQL Server\MSSQL\DATA\mastlog.ldf
tempdb C:\SQL ServerData\MSSQL10.MSSQL Server\MSSQL\DATA\tempdb.mdf
tempdb C:\SQL ServerData\MSSQL10.MSSQL Server\MSSQL\DATA\templog.ldf
model C:\SQL ServerData\MSSQL10.MSSQL Server\MSSQL\DATA\model.mdf
size max_size growth
----- -------- ----------
512 無制限 10%
160 無制限 10%
1024 無制限 10%
64 無制限 10%
288 無制限 128page(s)
/********************************************************************/
# 実行結果
http://www.insight-tec.com/mailmagazine/SQL_ref/sys.master_files_change1.png
/********************************************************************/
ここから、結果の中にある1つのファイルをピックアップして
情報を見ていきます。
1行目にあるmasterというデータベースのsizeには"512"と出力されています。
しかし、physical_nameで指定されているファイルのプロパティをみると、
実際のファイルサイズは4,194,304 バイトです。
#
http://www.insight-tec.com/mailmagazine/SQL_ref/master.mdf.png
では、SQLの結果で出力された"512"は何を示しているのでしょうか?
sys.master_filesの説明を見ると
"size列は、現在のファイル サイズ (8 KB ページ単位) "とあります。
よってこの512は、
「8KBのページ数が512個はいっています。」といっているわけです。
試しに、先ほどのsize部分がバイトで出力されるように修正します。
<< SQL文 >>
/********************************************************************/
SELECT
DB_NAME(database_id) dbname,
name,
file_id,
file_guid,
physical_name,
cast(size as decimal) *8*1024 [size],
case when max_size < 0 then N'無制限' else
CAST(max_size as nvarchar) end max_size,
case when growth = 0 then N'固定' else
CAST(growth as nvarchar) end +
case when is_percent_growth = 1 then N'%' else
N'page(s)' end growth
FROM
sys.master_files
;
/********************************************************************/
<< 実行結果(抜粋) >>
/********************************************************************/
dbname physical_name
------ -----------------------------------------------------------
master C:\SQL ServerData\MSSQL10.MSSQL Server\MSSQL\DATA\master.mdf
master C:\SQL ServerData\MSSQL10.MSSQL Server\MSSQL\DATA\mastlog.ldf
tempdb C:\SQL ServerData\MSSQL10.MSSQL Server\MSSQL\DATA\tempdb.mdf
tempdb C:\SQL ServerData\MSSQL10.MSSQL Server\MSSQL\DATA\templog.ldf
model C:\SQL ServerData\MSSQL10.MSSQL Server\MSSQL\DATA\model.mdf
size max_size growth
------- -------- ----------
4194304 無制限 10%
1310720 無制限 10%
8388608 無制限 10%
524288 無制限 10%
2359296 無制限 128page(s)
/********************************************************************/
# 実行結果
http://www.insight-tec.com/mailmagazine/SQL_ref/sys.master_files_change2.png
/********************************************************************/
これで、ファイルのプロパティで表示されていたファイルサイズと
SQL出力結果のsizeが一致し、
SQL Serverのページが8KBである事を実感できたかと思います。
======================================================================
データベースとデータファイル・ページ
======================================================================
先ほどまでの検証にて、
データファイルの中には"ページ"というものが存在している事を
感じていただけたかと思います。
今度はそのページとは何かをみていきます。
事前準備として、使用するデータベースとテーブルを作成します。
<< SQL文 >>
/********************************************************************/
USE [master]
GO
CREATE DATABASE mini ON PRIMARY
(
NAME = N'miniPri',
FILENAME = N'C:\SQL ServerData\miniPri.mdf' ,
SIZE = 3MB ,
FILEGROWTH = 1KB
),
FILEGROUP miniSec DEFAULT
(
NAME = N'miniSec',
FILENAME = N'C:\SQL ServerData\miniSec.mdf' ,
SIZE = 512KB ,
FILEGROWTH = 1KB
)
LOG ON
(
NAME = N'log',
FILENAME = N'C:\SQL ServerData\mini.ldf'
)
Go
USE [mini]
GO
CREATE TABLE [tb1](
[id] [decimal](18, 0) NOT NULL,
[col1] [nvarchar](4000) NULL,
[col2] [nvarchar](max) NULL,
[col3] [nvarchar](max) NULL,
CONSTRAINT [pktb1] PRIMARY KEY CLUSTERED
(
[id] ASC
)ON [miniSec]
) ON [miniSec]
GO
/********************************************************************/
ここでさらっと"エクステント"について記述します。
詳しくは、これ以降に記載しますが、
CREATE DATABASEで指定するFILEGROWTHの値は、
『指定したサイズを、最も近い 64 KB 単位の値に切り上げた数値』
が実際の設定値として適用されます。
領域の増加は"エクステント単位"で行われるのですが、
8ページ=1エクステント、1ページ=8KBと決まっているからです。
よって、増加の最小値が 8KB * 8 = 64KB になる・・・
ということを暗に示しています。
さて、話を元に戻しまして、
作成しただけの状態で、このデータベースのサイズを調べてみます。
次のSQLは
データベースに割り当てられたデータ領域を表示するSQLです。
<< SQL文 >>
/********************************************************************/
USE [mini]
GO
SELECT
*
FROM
sys.data_spaces;
/********************************************************************/
# MSDN
http://msdn.microsoft.com/ja-jp/library/ms190289.aspx
<< 実行結果 >>
/********************************************************************/
name data_space_id type type_desc is_default
------- ------------- ---- -------------- ----------
PRIMARY 1 FG ROWS_FILEGROUP 0
miniSec 2 FG ROWS_FILEGROUP 1
/********************************************************************/
この結果により、CREATE DATABASEのON以下で指定した
"PRIMARY"というファイルグループと
"miniSec"というファイルグループが表示されます。
次に、このデータベースのアロケーションユニットの一覧を取得してみます。
# アロケーションユニットについてはMSDNライブラリ参照
# MSDN
http://msdn.microsoft.com/ja-jp/library/ms189051.aspx
<< SQL文 >>
/********************************************************************/
USE [mini]
GO
SELECT
*
FROM
sys.allocation_units
;
/********************************************************************/
# MSDN
http://msdn.microsoft.com/ja-jp/library/ms189792.aspx
<< 実行結果(抜粋) >>
/********************************************************************/
allocation_unit_id type type_desc container_id
------------------ ---- ----------------- ------------------
72057594039828480 1 IN_ROW_DATA 72057594038779904
72057594039894016 3 ROW_OVERFLOW_DATA 72057594038779904
72057594039959552 2 LOB_DATA 72057594038779904
data_space_id total_pages used_pages data_pages
------------- ----------- ---------- ----------
2 0 0 0
2 0 0 0
2 0 0 0
/********************************************************************/
このSQL結果は100件強出力されているかと思います。
この出力結果が、ページの集合体である
アロケーションユニットの一覧結果になるのですが、
これだけを見ていても、情報がよく見えないと思いますので、
SQLを改変し、実行します。
<< SQL文 >>
/********************************************************************/
USE [mini]
GO
SELECT
sys.allocation_units.allocation_unit_id,
sys.allocation_units.type_desc,
sys.allocation_units.total_pages,
sys.allocation_units.used_pages,
sys.allocation_units.data_pages,
sys.partitions.object_id,
OBJECT_NAME(sys.partitions.object_id) object_desc,
sys.partitions.index_id,
sys.partitions.rows
FROM
sys.data_spaces join (
sys.allocation_units left outer join sys.partitions
ON
container_id =
CASE
WHEN sys.allocation_units.type % 2 = 1 THEN
sys.partitions.hobt_id
WHEN sys.allocation_units.type = 2 THEN
sys.partitions.partition_id
END ) ON sys.data_spaces.data_space_id =
sys.allocation_units.data_space_id
ORDER BY object_id
;
/********************************************************************/
<< 実行結果(抜粋) >>
/********************************************************************/
allocation_unit_id type_desc total_pages used_pages
-------------------- ----------------- ----------- -----------
72057594039828480 IN_ROW_DATA 0 0
72057594039894016 ROW_OVERFLOW_DATA 0 0
72057594039959552 LOB_DATA 0 0
data_pages object_id object_desc index_id rows
---------- ----------- ----------- -------- -----
0 2105058535 tb1 1 0
0 2105058535 tb1 1 0
0 2105058535 tb1 1 0
/********************************************************************/
これでどのオブジェクトが、どれぐらいの行数があり、
どれぐらいページを使用しているかが分るようになりました。
さらに突っ込んで、これをファイル/ファイルグループと繋げてみます。
<< SQL文 >>
/********************************************************************/
USE [mini]
GO
SELECT
sys.data_spaces.*,
sys.allocation_units.allocation_unit_id,
sys.allocation_units.type_desc,
sys.allocation_units.total_pages,
sys.allocation_units.used_pages,
sys.allocation_units.data_pages,
sys.partitions.object_id,
OBJECT_NAME(sys.partitions.object_id) object_desc,
sys.partitions.index_id,
sys.partitions.rows
FROM
sys.data_spaces join (
sys.allocation_units left outer join sys.partitions
ON
container_id =
CASE
WHEN sys.allocation_units.type % 2 = 1 THEN
sys.partitions.hobt_id
WHEN sys.allocation_units.type = 2 THEN
sys.partitions.partition_id
END ) ON sys.data_spaces.data_space_id =
sys.allocation_units.data_space_id
ORDER BY object_id
;
/********************************************************************/
<< 実行結果(抜粋) >>
/********************************************************************/
name data_space_id type type_desc is_default
------- ------------- ---- -------------- ----------
miniSec 2 FG ROWS_FILEGROUP 1
miniSec 2 FG ROWS_FILEGROUP 1
miniSec 2 FG ROWS_FILEGROUP 1
allocation_unit_id type_desc total_pages used_pages data_pages
------------------ ----------------- ----------- ---------- ----------
72057594039828480 IN_ROW_DATA 0 0 0
72057594039894016 ROW_OVERFLOW_DATA 0 0 0
72057594039959552 LOB_DATA 0 0 0
object_id object_desc index_id rows
----------- ----------- -------- ----
2105058535 tb1 1 0
2105058535 tb1 1 0
2105058535 tb1 1 0
/********************************************************************/
これで、ファイル/ファイルグループに格納されているページ数がいくつか、
格納されているオブジェクトが何で、
どれぐらいの行数あるのかが見えるようになりました。
ここでテーブルに1行データをいれて、
先ほどのSQLを再度実行してみたいと思います。
<< SQL文 >>
/********************************************************************/
insert into tb1 values ( 1, null, null, null);
/********************************************************************/
<< 実行結果(抜粋) >>
/********************************************************************/
name data_space_id type type_desc is_default
------- ------------- ---- -------------- ----------
miniSec 2 FG ROWS_FILEGROUP 1
miniSec 2 FG ROWS_FILEGROUP 1
miniSec 2 FG ROWS_FILEGROUP 1
allocation_unit_id type_desc total_pages used_pages data_pages
------------------ ----------------- ----------- ---------- ----------
72057594039828480 IN_ROW_DATA 2 2 1
72057594039894016 ROW_OVERFLOW_DATA 0 0 0
72057594039959552 LOB_DATA 0 0 0
object_id object_desc index_id rows
----------- ----------- -------- ----
2105058535 tb1 1 1
2105058535 tb1 1 1
2105058535 tb1 1 1
/********************************************************************/
データを1行追加した事で、tb1のIN_ROW_DATAが使用している
ページの数が2に増えました。
行データで1ページ、
nvarcharが格納されるページで1ページ使用しているので、
計2ページの使用になります。
さらに、1行追加して再実行します。
<< SQL文 >>
/********************************************************************/
insert into tb1 values ( 2, null, null, null);
/********************************************************************/
<< 実行結果(抜粋) >>
/********************************************************************/
name data_space_id type type_desc is_default
------- ------------- ---- -------------- ----------
miniSec 2 FG ROWS_FILEGROUP 1
miniSec 2 FG ROWS_FILEGROUP 1
miniSec 2 FG ROWS_FILEGROUP 1
allocation_unit_id type_desc total_pages used_pages data_pages
------------------ ----------------- ----------- ---------- ----------
72057594039828480 IN_ROW_DATA 2 2 1
72057594039894016 ROW_OVERFLOW_DATA 0 0 0
72057594039959552 LOB_DATA 0 0 0
object_id object_desc index_id rows
----------- ----------- -------- ----
2105058535 tb1 1 2
2105058535 tb1 1 2
2105058535 tb1 1 2
/********************************************************************/
今度は格納行数が2行に増えましたが、使用ページ数は増えていません。
よって、1ページには複数行のデータが格納されていることが分ります。
次に、tb1.col1に大きいバイト数のデータをUpdateをして、再実行します。
<< SQL文 >>
/********************************************************************/
USE [mini]
GO
UPDATE tb1
SET col1 = REPLICATE(N'~', 4000)
;
GO
SELECT
DATALENGTH(col1) col1_len
FROM
tb1
WHERE
id = 1
;
USE [mini]
GO
SELECT
id,
DATALENGTH(col1) col1_len
FROM
tb1
;
SELECT
sys.data_spaces.*,
sys.allocation_units.allocation_unit_id,
sys.allocation_units.type_desc,
sys.allocation_units.total_pages,
sys.allocation_units.used_pages,
sys.allocation_units.data_pages,
sys.partitions.object_id,
OBJECT_NAME(sys.partitions.object_id) object_desc,
sys.partitions.index_id,
sys.partitions.rows
FROM
sys.data_spaces join (
sys.allocation_units left outer join sys.partitions
ON
container_id =
CASE
WHEN sys.allocation_units.type % 2 = 1 THEN
sys.partitions.hobt_id
WHEN sys.allocation_units.type = 2 THEN
sys.partitions.partition_id
END ) ON sys.data_spaces.data_space_id =
sys.allocation_units.data_space_id
ORDER BY data_space_id
;
/********************************************************************/
<< 実行結果(抜粋) >>
/********************************************************************/
name data_space_id type type_desc is_default
------- ------------- ---- -------------- ----------
miniSec 2 FG ROWS_FILEGROUP 1
miniSec 2 FG ROWS_FILEGROUP 1
miniSec 2 FG ROWS_FILEGROUP 1
allocation_unit_id type_desc total_pages used_pages data_pages
------------------ ----------------- ----------- ---------- ----------
72057594039828480 IN_ROW_DATA 4 4 2
72057594039894016 ROW_OVERFLOW_DATA 0 0 0
72057594039959552 LOB_DATA 0 0 0
object_id object_desc index_id rows
----------- ----------- -------- ----
2105058535 tb1 1 2
2105058535 tb1 1 2
2105058535 tb1 1 2
/********************************************************************/
今度はtb1.col1のバイト数8,000バイト×2になったので、
1ページ(8KB)に格納きしれず、
tb1のIN_ROW_DATAが使用しているページ数が増えました。
同様にtb1.col2に大きいバイト数のデータをUpdateをして、再実行します。
<< SQL文 >>
/********************************************************************/
UPDATE tb1
SET col2 = REPLICATE(N'~', 4000)
;
USE [mini]
GO
SELECT
id,
DATALENGTH(col1) col1_len,
DATALENGTH(col2) col2_len
FROM
tb1
;
SELECT
sys.data_spaces.*,
sys.allocation_units.allocation_unit_id,
sys.allocation_units.type_desc,
sys.allocation_units.total_pages,
sys.allocation_units.used_pages,
sys.allocation_units.data_pages,
sys.partitions.object_id,
OBJECT_NAME(sys.partitions.object_id) object_desc,
sys.partitions.index_id,
sys.partitions.rows
FROM
sys.data_spaces join (
sys.allocation_units left outer join sys.partitions
ON
container_id =
CASE
WHEN sys.allocation_units.type % 2 = 1 THEN
sys.partitions.hobt_id
WHEN sys.allocation_units.type = 2 THEN
sys.partitions.partition_id
END ) ON sys.data_spaces.data_space_id =
sys.allocation_units.data_space_id
ORDER BY data_space_id
;
/********************************************************************/
<< 実行結果(抜粋) >>
/********************************************************************/
name data_space_id type type_desc is_default
------- ------------- ---- -------------- ----------
miniSec 2 FG ROWS_FILEGROUP 1
miniSec 2 FG ROWS_FILEGROUP 1
miniSec 2 FG ROWS_FILEGROUP 1
allocation_unit_id type_desc total_pages used_pages data_pages
------------------ ----------------- ----------- ---------- ----------
72057594039828480 IN_ROW_DATA 4 4 2
72057594039894016 ROW_OVERFLOW_DATA 0 0 0
72057594039959552 LOB_DATA 3 3 0
object_id object_desc index_id rows
----------- ----------- -------- ----
2105058535 tb1 1 2
2105058535 tb1 1 2
2105058535 tb1 1 2
/********************************************************************/
今度はtb1.col2のバイト数8,000バイト×2になったので、
1ページ(8KB)に格納きしれず、
tb1のLOB_DATAが使用しているページ数が増えました。
これは、tb1.col1 = nvarchar(4000) と定義されているのに対して、
tb1.col2 = nverchar(max)と定義されている違いです。
max指定をするとLOBと同じ様にデータが扱われ、
LOBとしてページが確保されることが分ります。
同様にtb1.col3の値も同じ様にUpdateすると、結果が以下のようになります。
<< 実行結果(抜粋) >>
/********************************************************************/
name data_space_id type type_desc is_default
------- ------------- ---- -------------- ----------
miniSec 2 FG ROWS_FILEGROUP 1
miniSec 2 FG ROWS_FILEGROUP 1
miniSec 2 FG ROWS_FILEGROUP 1
allocation_unit_id type_desc total_pages used_pages data_pages
------------------ ----------------- ----------- ---------- ----------
72057594039828480 IN_ROW_DATA 4 4 2
72057594039894016 ROW_OVERFLOW_DATA 3 3 0
72057594039959552 LOB_DATA 5 5 0
object_id object_desc index_id rows
----------- ----------- -------- ----
2105058535 tb1 1 2
2105058535 tb1 1 2
2105058535 tb1 1 2
/********************************************************************/
この様に、ページには複数行格納されているものもあれば、
複数ページで1つのデータを格納しているものもあります。
このあたりの詳細はMSDNを参照すると、より理解できるかと思います。
ページとエクステントについて
MSND
http://msdn.microsoft.com/ja-jp/library/ms190969.aspx
参照:8 KB を超える場合の行オーバーフロー データ
MSND
http://msdn.microsoft.com/ja-jp/library/ms186981.aspx
======================================================================
データファイルとエクステント
======================================================================
ここで話を最初のデータファイルの方に戻します。
このminiというデータベースを作成し、tb1というテーブルを作成、
レコード2件登録、col1, col2, col3とUpdateしてきました。
ここまでの状態で、mini.dbo.tb1がデータを格納するために使用している
ファイルのサイズは524,288 バイトになっていました。
この状態から、データをこのままで1件ずつ増やしていきたいと思います。
<< SQL文 >>
/********************************************************************/
INSERT INTO
tb1
SELECT
id + 1,
col1,
col2,
col3
FROM
tb1
WHERE
id = ( SELECT MAX(id) FROM tb1 )
;
/********************************************************************/
このSQLを何度も発行し、最初にデータの増減があった17行目で
データファイルのサイズやデータベースのページ数を取得してみます。
<< SQL文 >>
/********************************************************************/
SELECT
sys.data_spaces.*,
sys.allocation_units.allocation_unit_id,
sys.allocation_units.type_desc,
sys.allocation_units.total_pages,
sys.allocation_units.used_pages,
sys.allocation_units.data_pages,
sys.partitions.object_id,
OBJECT_NAME(sys.partitions.object_id) object_desc,
sys.partitions.index_id,
sys.partitions.rows
FROM
sys.data_spaces join (
sys.allocation_units left outer join sys.partitions
ON
container_id =
CASE
WHEN sys.allocation_units.type % 2 = 1 THEN
sys.partitions.hobt_id
WHEN sys.allocation_units.type = 2 THEN
sys.partitions.partition_id
END ) ON sys.data_spaces.data_space_id =
sys.allocation_units.data_space_id
ORDER BY data_space_id
;
SELECT
DB_NAME(database_id) dbname,
name,
file_id,
file_guid,
physical_name,
cast(size as decimal) *8*1024 [size],
case when max_size < 0 then N'無制限' else
CAST(max_size as nvarchar) end max_size,
case when growth = 0 then N'固定' else
CAST(growth as nvarchar) end +
case when is_percent_growth = 1 then N'%' else
N'page(s)' end growth
FROM
sys.master_files
;
/********************************************************************/
<< 実行結果(抜粋) >>
/********************************************************************/
name data_space_id type type_desc is_default
------- ------------- ---- -------------- ----------
miniSec 2 FG ROWS_FILEGROUP 1
miniSec 2 FG ROWS_FILEGROUP 1
miniSec 2 FG ROWS_FILEGROUP 1
allocation_unit_id type_desc total_pages used_pages data_pages
------------------ ----------------- ----------- ---------- ----------
72057594039828480 IN_ROW_DATA 4 4 2
72057594039894016 ROW_OVERFLOW_DATA 25 18 0
72057594039959552 LOB_DATA 41 35 0
object_id object_desc index_id rows
----------- ----------- -------- ----
2105058535 tb1 1 17
2105058535 tb1 1 17
2105058535 tb1 1 17
======================================================================
dbname physical_name size max_size growth
------ ---------------------------- ------- -------- ----------
mini C:\SQL ServerData\miniSec.mdf 655360 無制限 8page(s)
/********************************************************************/
ファイルサイズが524288バイトから655360バイトへ増加しました。
これによって
増加したページ数は128ページ、
増加したエクステント数は16エクステントだと分ります。
(655360 - 524288)/8192 = 16ページ
16 / 8 = 2 エクステント
次はINSERTのデータを少なくして、増加をみてみます。
<< SQL文 >>
/********************************************************************/
INSERT INTO
tb1
SELECT
id + 1,
col1,
null,
null
FROM
tb1
WHERE
id = ( SELECT MAX(id) FROM tb1 )
;
/********************************************************************/
このSQLを何度も発行し、最初にデータの増減があった状態は
以下のようになります。
<< 実行結果(抜粋) >>
/********************************************************************/
name data_space_id type type_desc is_default
------- ------------- ---- -------------- ----------
miniSec 2 FG ROWS_FILEGROUP 1
miniSec 2 FG ROWS_FILEGROUP 1
miniSec 2 FG ROWS_FILEGROUP 1
allocation_unit_id type_desc total_pages used_pages data_pages
------------------ ----------------- ----------- ---------- ----------
72057594039828480 IN_ROW_DATA 7 7 5
72057594039894016 ROW_OVERFLOW_DATA 25 18 0
72057594039959552 LOB_DATA 41 35 0
object_id object_desc index_id rows
----------- ----------- -------- ----
2105058535 tb1 1 20
2105058535 tb1 1 20
2105058535 tb1 1 20
dbname physical_name size max_size growth
------ ---------------------------- ------- -------- ----------
mini C:\SQL ServerData\miniSec.mdf 720896 無制限 8page(s)
/********************************************************************/
ファイルサイズが655360バイトから720896バイトへ増加しました。
これによって増加したページ数は8ページ、
増加したエクステント数は1エクステントだと分ります。
これまでの、データ増加は1ページより大きいデータを追加してきました。
では、1ページ未満のデータを数件いれて増加量を見てみようと思います。
<< SQL文 >>
/********************************************************************/
INSERT INTO
tb1
SELECT
( SELECT MAX(id) FROM tb1 ) + 1,
REPLICATE(N'0',1000),
null,
null
;
/********************************************************************/
このSQLを何度も発行し、最初にデータの増減があった状態は
以下のようになります。
<< 実行結果(抜粋) >>
/********************************************************************/
name data_space_id type type_desc is_default
------- ------------- ---- -------------- ----------
miniSec 2 FG ROWS_FILEGROUP 1
miniSec 2 FG ROWS_FILEGROUP 1
miniSec 2 FG ROWS_FILEGROUP 1
allocation_unit_id type_desc total_pages used_pages data_pages
------------------ ----------------- ----------- ---------- ----------
72057594039828480 IN_ROW_DATA 17 10 8
72057594039894016 ROW_OVERFLOW_DATA 25 18 0
72057594039959552 LOB_DATA 41 35 0
object_id object_desc index_id rows
----------- ----------- -------- ----
2105058535 tb1 1 29
2105058535 tb1 1 29
2105058535 tb1 1 29
dbname physical_name size max_size growth
------ ---------------------------- ------- -------- ----------
mini C:\SQL ServerData\miniSec.mdf 786432 無制限 8page(s)
/********************************************************************/
ファイルサイズが720896バイトから786432バイトへ増加しました。
これによって増加したページ数は8ページ、
増加したエクステント数は1エクステントだと分ります。
なぜ、この8ページで増加するのかというと、
CREATE DATABASEで指定したFILEGROWTH=1KBが
SQL Serverによって、1KBから最も近い64 KB 単位の値に
切り上げられて増加するからです。
よって、ファイルサイズの最小増加は8ページ単位になります。
======================================================================
まとめ と 考察
======================================================================
・ データベースにはデータが格納されるデータファイルと、
ログが格納されるログファイルとを持っている。
-> これによって、SQL Serverはデータベースごとに
ログファイルを持つ構造になっていることがわかる。
よって、インスタンス毎ではなく、
データベース毎のバックアップ & 復旧が行われる必要がある。
・ データベースはページという単位を持っていて
ページはデータファイルの中に書きこまれる最小単位である。
また、ページにはテーブルのデータが格納されていて、
1ページに複数行格納されている。
ただし、8KBを超えるデータの場合、
ページをまたがってデータが格納される。
-> 1ページは8KBという制限があるので、
列長を8KBよりも大きくするときは、性能面での考慮が必要。
(ページ毎にバッファへのデータ入出力が行われるため)
・ データが格納できるページが無くなると、ファイルの拡張が発生する。
また、データファイルは最小64KB単位で増えていく。
よって、8ページ=1エクステント単位で増えていく。
-> SQL Serverのデータファイルを格納するディスクが
データ増加により、知らない間に圧迫されないか
気を払う必要がある��
特に、無制限拡張をしている場合は
使えるだけどんどんファイルサイズが増加するので注意が必要。
・ データファイルには、ファイルとグループの2種類がある。
-> ファイルグループを使い、実ファイルを
複数ディスクに分散させることが出来る。
┏─────────────────────────────────┓
┃ご質問について ┃
┗─────────────────────────────────┛
<皆様からのご質問を受付けております>
皆様のご質問にはできるだけ、お答えしたいと思っています。
すべてのご質問にお答えすることはできないかもしれませんが、
適宜メルマガ内でとりあげていく予定ですので、是非お気軽に下記アドレス
までお寄せください。
ご意見、ご感想などもお待ちしておりますっ!!
wlmailhtml:{FFB7FEE3-FD66-4A13-AECC-755EBDF825BF}mid://00000000/!x-usc:mailto:letter@insight-tec.co.jp
┏─────────────────────────────────┓
┃編集者より ┃
┗─────────────────────────────────┛
初めまして!!この度は、どっぷりリファレン中をご購読いただきまして、本
当に!本当に!ありがとうございますっ♪初回はいかがでしたでしょうか??
感想&ご質問等ありましたらご遠慮なくお知らせいただけると、とても、とて
も、嬉しいですっ!!不定期の配信となりますが、次回の配信を首をながーく
してお待ちくださいね☆ by TI
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
<えす!エス!レスキュー SQL Server -どっぷりリファレン中!!->
発行/編集:株式会社インサイトテクノロジー
http://www.insight-tec.com
wlmailhtml:{FFB7FEE3-FD66-4A13-AECC-755EBDF825BF}mid://00000000/!x-usc:mailto:letter@insight-tec.co.jp
本メールマガジンに掲載された記事を許可なく転載することを禁じます。
Copyright(c) 2009, Insight Technology, Inc., All Rights Reserved.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
※本メールマガジンは株式会社インサイトテクノロジーより許諾を受けて、紹介のために掲載しています。
0 Comments
Comments
Your comment has been posted.
Close
Thank you, your comment requires moderation so it may take a while to appear.
Close
Leave a Comment
Name
Comment
Post