ADSI Notes - Diogo Lopes

Search

Search IconIcon to open search

Lab 02 - Storage and file structure

Last updated Apr 18, 2023

Lab02

.mdf files* Data files contain data and objects such as tables, indexes, stored procedures, and views. large file (in the AdventureWorks2019 DB Properties, this file has an unlimited MAXSIZE)

.ldf Log files contain the information that is required to recover all transactions in the database. smaller sized file (in the AdventureWorks2019 DB Properties, this file has an ~2GB MAXSIZE)

# Creating an ExampleDB

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
CREATE DATABASE ExampleDB
ON PRIMARY (
	NAME = ExampleDB_File1,
	FILENAME= 'C:\Temp\ExampleDB_File1.mdf',
	SIZE = 30MB,
	FILEGROWTH = 15%),
FILEGROUP SECONDARY_1 (
	NAME = ExampleDB_File2,
	FILENAME= 'C:\Temp\ExampleDB_File2.ndf',
	SIZE = 20MB,
	FILEGROWTH = 2048KB),
FILEGROUP SECONDARY_2 (
	NAME = ExampleDB_File3,
	FILENAME= 'C:\Temp\ExampleDB_File3.ndf',
	SIZE = 30MB,
	FILEGROWTH = 15%)
LOG ON (
	NAME = ExampleDB_Log,
	FILENAME = 'C:\Temp\ExampleDB_Log.ldf',
	SIZE = 5MB,
	MAXSIZE = 100MB,
	FILEGROWTH = 15%);

3 Different File Groups

Log file initial value: 5MB Log file max value: 100MB

Primary Data file on initial size: 30MB Data file on FILEGROUP SECONDARY_1 initial size: 20MB Data file on FILEGROUP SECONDARY_2 initial size: 30MB Data files have unlimited max value

All files grow 15% everytime more storage in needed, except for the data file in the SECONDARY_1 file group, which grows 2MB

# Creating an ExampleTable
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
USE ExampleDB;

CREATE PARTITION FUNCTION ExampleDB_Range1(INT)
AS RANGE RIGHT FOR VALUES (10);

CREATE PARTITION SCHEME ExampleDB_PartScheme1
AS PARTITION ExampleDB_Range1 TO
(SECONDARY_1, SECONDARY_2);

CREATE TABLE ExampleTable (
	VALUE1 INT NOT NULL,
	VALUE2 INT NOT NULL,
	STR1 VARCHAR(50)
) ON ExampleDB_PartScheme1(VALUE1);

Note: Remember that, when creating a database table, if a schema is not specified, the default schema is dbo

# Populating ExampleTable
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
USE ExampleDB;
INSERT INTO ExampleTable VALUES (8, 40, 'C');
INSERT INTO ExampleTable VALUES (8, 20, 'A');
INSERT INTO ExampleTable VALUES (9, 30, 'B');
INSERT INTO ExampleTable VALUES (9, 40, 'C');
INSERT INTO ExampleTable VALUES (10, 30, 'B');
INSERT INTO ExampleTable VALUES (10, 40, 'C');
INSERT INTO ExampleTable VALUES (11, 20, 'A');
INSERT INTO ExampleTable VALUES (11, 40, 'C');
INSERT INTO ExampleTable VALUES (12, 20, 'A');
# Info from System Views
1
2
3
4
5
6
7
SELECT fg.name, p.rows
FROM sys.partitions AS p,
	sys.destination_data_spaces AS dds,
	sys.filegroups AS fg
WHERE p.object_id = OBJECT_ID('ExampleTable')
	AND p.partition_number = dds.destination_id
	AND dds.data_space_id = fg.data_space_id;

Results:

namerows
SECONDARY_14
SECONDARY_25

# Investigating contents of a data file in SQL Server

When SQL Server needs to manage space (allocate new pages, or deallocate existing ones), it does so in groups of 8. A group of 8 pages is called an extent. An extent is 8 physically contiguous pages, or 64 KB. This means SQL Server databases have 16 extents per megabyte.

SQL Server has two types of extents: uniform and mixed. Uniform extents are owned by a single object; all eight pages in the extent can only be used by the owning object. Mixed extents are shared by up to 8 objects; each of the eight pages in the extent can be owned by a different object.

Note: Log files (.ldf) do not contain pages; they contain a series of log records.

# Page Allocations

Using system function:

1
2
3
4
5
SELECT partition_id, allocated_page_page_id
FROM sys.dm_db_database_page_allocations(db_id('ExampleDB'),
				object_id('ExampleTable'),
				NULL, NULL, 'DETAILED')
WHERE page_type_desc = 'DATA_PAGE';

Results:

partition_idallocated_page_page_id
18
28

Note*: In our case there are two partitions, and the page ID might happen to be the same in each of those partitions.

Using system views:

1
2
3
4
5
6
7
SELECT p.partition_number, df.file_id, df.physical_name
FROM sys.partitions AS p,
	sys.destination_data_spaces AS dds,
	sys.database_files AS df
WHERE p.object_id = OBJECT_ID('ExampleTable')
	AND p.partition_number = dds.destination_id
	AND dds.data_space_id = df.data_space_id;

Results:

partition_numberfile_idphysical_name
13C:\Temp\ExampleDB_File2.ndf
24C:\Temp\ExampleDB_File3.ndf

Note: In our case, each partition is in a different file, and the file ID identifies each of those physical files.

# DBCC - Database Console Commands
1
2
DBCC TRACEON(3604);
DBCC PAGE('ExampleDB', 3, 8, 1);

DBCC (database console commands) are special SQL Server commands used for database administration, maintenance and troubleshooting.


(…) Slot 0, (…) 0000000000000000: 30000c00 08000000 28000000 03000001 00140043 0…….(……….C

Slot 1, (…) 0000000000000000: 30000c00 08000000 14000000 03000001 00140041 0………………A

Slot 2, (…) 0000000000000000: 30000c00 09000000 1e000000 03000001 00140042 0… …………..B

Slot 3, (…) 0000000000000000: 30000c00 09000000 28000000 03000001 00140043 0… …(……….C


If we change the command to show info on file ID 4, the 5 records end with B, C, A, C, A.

# SET STATISTICS IO ON;
1
2
3
USE ExampleDB;
SET STATISTICS IO ON;
SELECT * FROM ExampleTable;

Going to the Messages Tab

  1. Enabling Include Actual Execution Plan (Ctrl+M)
  2. Re-executing only the SELECT query
  3. Switching to the Execution Plan Tab

While hovering the Table Scan, we can see some stats, including:

# IAM Page
1
2
3
4
5
SELECT partition_id, allocated_page_page_id
FROM sys.dm_db_database_page_allocations(db_id('ExampleDB'),
					object_id('ExampleTable'),
					NULL, NULL, 'DETAILED')
WHERE page_type_desc = 'IAM_PAGE';

Results:

partition_idallocated_page_page_id
116
216

As the table grows pages are allocated in groups of 8 (extents).

As the file grows, SQL Server needs to know which extents contain pages of a given object. For this purpose, SQL Server uses a special type of page, called IAM page (Index Allocation Map).

Internally, an IAM page contains a bitmap where each bit refers to an extent in the file, and the bit value (1 or 0) indicates whether the extent has been allocated to the object or not

Note: An IAM page can cover about 4 GB of data, so the table would have to grow considerably before another IAM page needs to be created.

Using DBCC:

1
2
DBCC TRACEON(3604);
DBCC PAGE('ExampleDB', 3, 16, 1);

Lab 02 Screenshot