Là SQL Server DBA, chúng tôi luôn quan tâm đến một trong những thứ quan trọng nhất đối với doanh nghiệp, đó là dữ liệu. Trong một số trường hợp, các ứng dụng có thể trở nên khá phức tạp và bạn sẽ có rất nhiều bảng cơ sở dữ liệu nằm rải rác xung quanh (các) phiên bản SQL Server của mình. Điều này có thể dẫn đến một số bất tiện, chẳng hạn như:
- Biết cách dữ liệu của bạn hoạt động hàng ngày, xét về xu hướng tăng trưởng (không gian và / hoặc số lượng hàng).
- Biết các bảng cơ sở dữ liệu yêu cầu (hoặc sẽ yêu cầu) một chiến lược cụ thể / khác để lưu trữ dữ liệu vì nó đang phát triển quá nhanh.
- Biết bảng cơ sở dữ liệu nào của bạn chiếm quá nhiều dung lượng, có thể dẫn đến hạn chế về bộ nhớ.
Do tầm quan trọng của những chi tiết này, tôi đã tạo một số Thủ tục được lưu trữ có thể giúp ích rất nhiều cho bất kỳ DBA SQL Server nào muốn theo dõi thông tin liên quan đến các bảng cơ sở dữ liệu trong môi trường của họ. Tin tôi đi, một trong số họ rất tuyệt.
Cân nhắc ban đầu
- Đảm bảo rằng tài khoản thực hiện Quy trình đã lưu trữ này có đủ đặc quyền. Bạn có thể bắt đầu với sysadmin và sau đó đi càng chi tiết càng tốt để đảm bảo người dùng có tối thiểu các đặc quyền cần thiết để SP hoạt động bình thường.
- Các đối tượng cơ sở dữ liệu (bảng cơ sở dữ liệu và quy trình được lưu trữ) sẽ được tạo bên trong cơ sở dữ liệu được chọn tại thời điểm tập lệnh được thực thi, vì vậy hãy chọn cẩn thận.
- Tập lệnh được tạo theo cách có thể được thực thi nhiều lần mà không gây ra lỗi cho bạn. Đối với Thủ tục được lưu trữ, tôi đã sử dụng câu lệnh “TẠO HOẶC THAY THẾ THỦ TỤC”, có sẵn kể từ SQL Server 2016 SP1. Đó là lý do tại sao đừng ngạc nhiên nếu nó không hoạt động trơn tru trong phiên bản cũ hơn.
- Thoải mái thay đổi tên của các đối tượng cơ sở dữ liệu đã tạo.
- Chú ý đến các tham số của Thủ tục đã lưu trữ thu thập dữ liệu thô. Chúng có thể rất quan trọng trong một chiến lược thu thập dữ liệu mạnh mẽ để hình dung xu hướng.
Làm thế nào để sử dụng các thủ tục đã lưu trữ?
- Sao chép và dán Mã T-SQL (có sẵn trong bài viết này).
- SP đầu tiên mong đợi 2 tham số:
- @ persData:‘Y’ nếu DBA muốn lưu kết quả đầu ra trong bảng đích và ‘N’ nếu DBA muốn xem kết quả trực tiếp.
- @truncateTable:‘Y’ để cắt ngắn bảng trước khi lưu trữ dữ liệu đã ghi và ‘N’ nếu dữ liệu hiện tại được giữ trong bảng. Xin lưu ý rằng giá trị của thông số này không liên quan nếu giá trị của thông số @persistData là "N".
- SP thứ hai yêu cầu 1 tham số:
- @targetParameter:Tên của cột được sử dụng để chuyển thông tin đã thu thập.
Các trường được trình bày và ý nghĩa của chúng
- database_name: tên của cơ sở dữ liệu nơi bảng nằm.
- giản đồ: tên của lược đồ nơi có bảng.
- tên_bảng: trình giữ chỗ cho tên của bảng.
- row_count: số hàng mà bảng hiện có.
- total_space_mb: số lượng MegaByte được phân bổ cho bảng.
- used_space_mb: số lượng MegaByte thực sự được sử dụng trong bảng.
- used_space_mb: số lượng MegaByte mà bảng không sử dụng.
- ngày_sao_nhiên: ngày / giờ khi bảng được tạo.
- data_collection_timestamp: chỉ hiển thị nếu ‘Y’ được chuyển cho tham số @persistData. Nó được sử dụng để biết khi nào SP được thực thi và thông tin đã được lưu thành công trong bảng DBA_Tables.
Kiểm tra thực thi
Tôi sẽ trình bày một số cách thực thi của Quy trình được lưu trữ:
/ * Hiển thị thông tin bảng cho tất cả cơ sở dữ liệu người dùng * /
EXEC GetTablesData @persistData = 'N',@truncateTable = 'N'
/ * Giữ nguyên thông tin của các bảng cơ sở dữ liệu và truy vấn bảng đích, cắt bớt bảng đích trước * /
EXEC GetTablesData @persistData = 'Y',@truncateTable = 'Y'
SELECT * FROM DBA_Tables
Truy vấn bên
* Truy vấn để xem các bảng cơ sở dữ liệu được sắp xếp từ số hàng lớn nhất đến hàng thấp nhất.
SELECT * FROM DBA_Tables ORDER BY row_count DESC;
* Truy vấn để xem các bảng cơ sở dữ liệu được sắp xếp từ tổng không gian lớn nhất đến thấp nhất.
SELECT * FROM DBA_Tables ORDER BY total_space_mb DESC;
* Truy vấn để xem các bảng cơ sở dữ liệu được sắp xếp từ không gian được sử dụng lớn nhất đến thấp nhất.
SELECT * FROM DBA_Tables ORDER BY used_space_mb DESC;
* Truy vấn để xem các bảng cơ sở dữ liệu được sắp xếp từ không gian chưa sử dụng lớn nhất đến thấp nhất.
SELECT * FROM DBA_Tables ORDER BY unused_space_mb DESC;
* Truy vấn để xem các bảng cơ sở dữ liệu được sắp xếp theo ngày tạo, từ mới nhất đến cũ nhất.
SELECT * FROM DBA_Tables ORDER BY created_date DESC;
Đây là mã hoàn chỉnh của Quy trình đã lưu trữ để nắm bắt thông tin của các bảng cơ sở dữ liệu:
* Ở phần đầu của tập lệnh, bạn sẽ thấy giá trị mặc định mà Thủ tục được lưu trữ giả định nếu không có giá trị nào được chuyển cho mỗi tham số.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE OR ALTER PROCEDURE [dbo].[GetTablesData]
@persistData CHAR(1) = 'Y',
@truncateTable CHAR(1) = 'Y'
AS
BEGIN
SET NOCOUNT ON
DECLARE @command NVARCHAR(MAX)
DECLARE @Tmp_TablesInformation TABLE(
[database] [VARCHAR](255) NOT NULL,
[schema] [VARCHAR](64) NOT NULL,
[table] [VARCHAR](255) NOT NULL,
[row_count] [BIGINT]NOT NULL,
[total_space_mb] [DECIMAL](15,2) NOT NULL,
[used_space_mb] [DECIMAL](15,2) NOT NULL,
[unused_space_mb] [DECIMAL](15,2) NOT NULL,
[created_date] [DATETIME] NOT NULL
)
SELECT @command = '
USE [?]
IF DB_ID(''?'') > 4
BEGIN
SELECT
''?'',
s.Name AS [schema],
t.NAME AS [table],
p.rows AS row_count,
CAST(ROUND(((SUM(a.total_pages) * 8) / 1024.00), 2) AS DECIMAL(15, 2)) AS total_space_mb,
CAST(ROUND(((SUM(a.used_pages) * 8) / 1024.00), 2) AS DECIMAL(15, 2)) AS used_space_mb,
CAST(ROUND(((SUM(a.total_pages) - SUM(a.used_pages)) * 8) / 1024.00, 2) AS DECIMAL(15, 2)) AS unused_space_mb,
t.create_date as created_date
FROM sys.tables t
INNER JOIN sys.indexes i ON t.OBJECT_ID = i.object_id
INNER JOIN sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
INNER JOIN sys.allocation_units a ON p.partition_id = a.container_id
LEFT OUTER JOIN sys.schemas s ON t.schema_id = s.schema_id
WHERE t.NAME NOT LIKE ''dt%''
AND t.is_ms_shipped = 0
AND i.OBJECT_ID > 255
GROUP BY t.Name, s.Name, p.Rows,t.create_date
ORDER BY total_space_mb DESC, t.Name
END'
INSERT INTO @Tmp_TablesInformation
EXEC sp_MSForEachDB @command
IF @persistData = 'N'
SELECT * FROM @Tmp_TablesInformation
ELSE
BEGIN
IF(@truncateTable = 'Y')
TRUNCATE TABLE DBA_Tables
INSERT INTO DBA_Tables
SELECT *,GETDATE() FROM @Tmp_TablesInformation ORDER BY [database],[schema],[table]
END
END
GO
Cho đến thời điểm này, thông tin có vẻ hơi khô khan, nhưng hãy để tôi thay đổi nhận thức đó với việc trình bày một Quy trình được lưu trữ bổ sung. Mục đích chính của nó là chuyển đổi thông tin được thu thập trong bảng mục tiêu để làm nguồn cho các báo cáo xu hướng.
Đây là cách bạn có thể thực hiện Thủ tục đã lưu trữ:
* Với mục đích trình diễn, tôi đã chèn các bản ghi thủ công vào bảng đích có tên là t1 để mô phỏng việc thực thi Thủ tục được Lưu trữ thông thường của tôi.
* Tập hợp kết quả hơi rộng, vì vậy tôi sẽ chụp một vài ảnh chụp màn hình để hiển thị toàn bộ kết quả đầu ra.
EXEC TransposeTablesInformation @targetParmeter = 'row_count'
Bài học rút ra chính
- Nếu bạn tự động hóa việc thực thi tập lệnh điền vào bảng đích, bạn có thể nhận thấy ngay lập tức nếu có sự cố xảy ra với nó hoặc với dữ liệu của bạn. Hãy xem dữ liệu cho bảng ‘t1’ và cột ‘15’. Bạn có thể thấy NULL ở đó được thực hiện có chủ đích để cho bạn thấy điều gì đó có thể xảy ra.
- Với kiểu xem này, bạn có thể thấy một hành vi đặc biệt đối với các bảng cơ sở dữ liệu quan trọng / quan trọng nhất.
- Tôi là ví dụ đã cho, tôi đã chọn trường 'row_count' của bảng mục tiêu, nhưng bạn có thể chọn bất kỳ trường số nào khác làm tham số và nhận cùng một định dạng bảng, nhưng với dữ liệu khác.
- Đừng lo lắng, nếu bạn chỉ định một tham số không hợp lệ, thì Thủ tục đã lưu trữ sẽ cảnh báo bạn và ngừng thực thi nó.
Đây là mã hoàn chỉnh của Quy trình đã lưu trữ để chuyển đổi thông tin của bảng đích:
* Ở phần đầu của tập lệnh, bạn sẽ thấy giá trị mặc định mà Thủ tục được lưu trữ giả định nếu không có giá trị nào được chuyển cho mỗi tham số.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE OR ALTER PROCEDURE [dbo].[TransposeTablesInformation]
@targetParameter NVARCHAR(15) = 'row_count'
AS
BEGIN
SET NOCOUNT ON;
IF (@targetParameter <> 'row_count' AND @targetParameter <> 'total_space_mb' AND @targetParameter <> 'used_space_mb' AND @targetParameter <> 'unused_space_mb')
BEGIN
PRINT 'Please specify a valid parameter!'
PRINT 'i.e. row_count | total_space_mb | used_space_mb | unused_space_mb'
RETURN
END
ELSE
BEGIN
CREATE TABLE #TablesInformation(
[database] [VARCHAR](255) NOT NULL,
[schema] [VARCHAR](64) NOT NULL,
[table] [VARCHAR](255) NOT NULL,
[1] [DECIMAL](10,2) NULL,
[2] [DECIMAL](10,2) NULL,
[3] [DECIMAL](10,2) NULL,
[4] [DECIMAL](10,2) NULL,
[5] [DECIMAL](10,2) NULL,
[6] [DECIMAL](10,2) NULL,
[7] [DECIMAL](10,2) NULL,
[8] [DECIMAL](10,2) NULL,
[9] [DECIMAL](10,2) NULL,
[10] [DECIMAL](10,2) NULL,
[11] [DECIMAL](10,2) NULL,
[12] [DECIMAL](10,2) NULL,
[13] [DECIMAL](10,2) NULL,
[14] [DECIMAL](10,2) NULL,
[15] [DECIMAL](10,2) NULL,
[16] [DECIMAL](10,2) NULL,
[17] [DECIMAL](10,2) NULL,
[18] [DECIMAL](10,2) NULL,
[19] [DECIMAL](10,2) NULL,
[20] [DECIMAL](10,2) NULL,
[21] [DECIMAL](10,2) NULL,
[22] [DECIMAL](10,2) NULL,
[23] [DECIMAL](10,2) NULL,
[24] [DECIMAL](10,2) NULL,
[25] [DECIMAL](10,2) NULL,
[26] [DECIMAL](10,2) NULL,
[27] [DECIMAL](10,2) NULL,
[28] [DECIMAL](10,2) NULL,
[29] [DECIMAL](10,2) NULL,
[30] [DECIMAL](10,2) NULL,
[31] [DECIMAL](10,2) NULL
)
INSERT INTO #TablesInformation([database],[schema],[table])
SELECT DISTINCT [database_name],[schema],[table_name]
FROM DBA_Tables
ORDER BY [database_name],[schema],table_name
DECLARE @databaseName NVARCHAR(255)
DECLARE @schemaName NVARCHAR(64)
DECLARE @tableName NVARCHAR(255)
DECLARE @value DECIMAL(10,2)
DECLARE @dataTimestamp DATETIME
DECLARE @sqlCommand NVARCHAR(MAX)
IF(@targetParameter = 'row_count')
BEGIN
DECLARE TablesCursor CURSOR FOR
SELECT
[database_name],
[schema],
[table_name],
[row_count],
[data_collection_timestamp]
FROM DBA_Tables
ORDER BY [database_name],[schema],table_name
END
IF(@targetParameter = 'total_space_mb')
BEGIN
DECLARE TablesCursor CURSOR FOR
SELECT
[database_name],
[schema],
[table_name],
[total_space_mb],
[data_collection_timestamp]
FROM DBA_Tables
ORDER BY [database_name],[schema],table_name
END
IF(@targetParameter = 'used_space_mb')
BEGIN
DECLARE TablesCursor CURSOR FOR
SELECT
[database_name],
[schema],
[table_name],
[used_space_mb],
[data_collection_timestamp]
FROM DBA_Tables
ORDER BY [database_name],[schema],table_name
END
IF(@targetParameter = 'unused_space_mb')
BEGIN
DECLARE TablesCursor CURSOR FOR
SELECT
[database_name],
[schema],
[table_name],
[unused_space_mb],
[data_collection_timestamp]
FROM DBA_Tables
ORDER BY [database_name],[schema],table_name
END
OPEN TablesCursor
FETCH NEXT FROM TablesCursor INTO @databaseName,@schemaName,@tableName,@value,@dataTimestamp
WHILE(@@FETCH_STATUS = 0)
BEGIN
SET @sqlCommand = CONCAT('
UPDATE #TablesInformation
SET [',DAY(@dataTimestamp),'] = ',@value,'
WHERE [database] = ',CHAR(39),@databaseName,CHAR(39),'
AND [schema] = ',CHAR(39),@schemaName+CHAR(39),'
AND [table] = ',CHAR(39),@tableName+CHAR(39),'
')
EXEC(@sqlCommand)
FETCH NEXT FROM TablesCursor INTO @databaseName,@schemaName,@tableName,@value,@dataTimestamp
END
CLOSE TablesCursor
DEALLOCATE TablesCursor
IF(@targetParameter = 'row_count')
SELECT [database],
[schema],
[table],
CONVERT(INT,[1]) AS [1],
CONVERT(INT,[2]) AS [2],
CONVERT(INT,[3]) AS [3],
CONVERT(INT,[4]) AS [4],
CONVERT(INT,[5]) AS [5],
CONVERT(INT,[6]) AS [6],
CONVERT(INT,[7]) AS [7],
CONVERT(INT,[8]) AS [8],
CONVERT(INT,[9]) AS [9],
CONVERT(INT,[10]) AS [10],
CONVERT(INT,[11]) AS [11],
CONVERT(INT,[12]) AS [12],
CONVERT(INT,[13]) AS [13],
CONVERT(INT,[14]) AS [14],
CONVERT(INT,[15]) AS [15],
CONVERT(INT,[16]) AS [16],
CONVERT(INT,[17]) AS [17],
CONVERT(INT,[18]) AS [18],
CONVERT(INT,[19]) AS [19],
CONVERT(INT,[20]) AS [20],
CONVERT(INT,[21]) AS [21],
CONVERT(INT,[22]) AS [22],
CONVERT(INT,[23]) AS [23],
CONVERT(INT,[24]) AS [24],
CONVERT(INT,[25]) AS [25],
CONVERT(INT,[26]) AS [26],
CONVERT(INT,[27]) AS [27],
CONVERT(INT,[28]) AS [28],
CONVERT(INT,[29]) AS [29],
CONVERT(INT,[30]) AS [30],
CONVERT(INT,[31]) AS [31]
FROM #TablesInformation
ELSE
SELECT * FROM #TablesInformation
END
END
GO
Kết luận
- Bạn có thể triển khai SP thu thập dữ liệu trong mọi phiên bản SQL Server dưới sự hỗ trợ của bạn và triển khai cơ chế cảnh báo trên toàn bộ ngăn xếp các phiên bản được hỗ trợ của bạn.
- Nếu bạn triển khai công việc đại lý truy vấn thông tin này tương đối thường xuyên, bạn có thể luôn dẫn đầu trò chơi về việc biết dữ liệu của bạn hoạt động như thế nào trong tháng. Tất nhiên, bạn có thể đi xa hơn nữa và lưu trữ dữ liệu được thu thập hàng tháng để có một bức tranh lớn hơn nữa; bạn phải thực hiện một số chỉnh sửa đối với mã, nhưng nó hoàn toàn xứng đáng.
- Đảm bảo kiểm tra cơ chế này đúng cách trong môi trường hộp cát và khi bạn đang lên kế hoạch triển khai sản xuất, hãy đảm bảo chọn khoảng thời gian hoạt động thấp.
- Thu thập thông tin kiểu này có thể giúp phân biệt DBA với nhau. Có lẽ có 3 công cụ của bên có thể làm được điều tương tự, và thậm chí nhiều hơn nữa, nhưng không phải ai cũng có đủ ngân sách để mua. Tôi hy vọng điều này có thể giúp ích cho bất kỳ ai quyết định sử dụng nó trong môi trường của họ.