当数据量过大,从数据层面可以按月分表,报表查询时可以根据,查询时间来计算查询的年月,查询对应的表
1、按月分表:
存储过程SP_BRANCH_TABLE_TEST
以下存储过程分表,加了索引可以方便后续查询
USE [DASHBOARD]
GO
/****** Object: StoredProcedure [dbo].[SP_BRANCH_TABLE_TEST] Script Date: 2024/7/5 10:01:31 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
--/*********************************************************************************************************
--建立者: DQY 日期﹕2024-04-08
--調用的程序﹕
--說明﹕SP_BRANCH_TABLE_TEST
--更新記錄﹕
-- 日期 更改人 更新說明
------------------ ------------- --------------------------------------------
-- 2024-04-08 dqy 新增 测试数据水平分割表数据 【月/表】
-- 2024-04-17 dqy 新增 测试项 水平分割表数据 【月/表】
----*********************************************************************************************************/
--调用 EXECUTE [dbo].[SP_BRANCH_TABLE_TEST]
ALTER PROCEDURE [dbo].[SP_BRANCH_TABLE_TEST]
AS
BEGIN
DECLARE @testTableName NVARCHAR(50); --测试
DECLARE @sql NVARCHAR(MAX);
SET @testTableName = N'PROD_TEST_DET_' + FORMAT(DATEADD(MONTH, -1, GETDATE()), 'yyyyMM');
SET @sql = N'
/*创建PROD_TEST_DET分表*/
IF OBJECT_ID(''' + @testTableName + ''') IS NOT NULL
DROP TABLE ' + @testTableName + ';
SELECT TOP 0 *
INTO ' + @testTableName + '
FROM PROD_TEST_DET WITH (NOLOCK);
--分表索引
CREATE CLUSTERED INDEX [IX_PSTP] ON ' + @testTableName + ' ([PROJ_CODE],[PROCESS_ID],[LOT_NO],[MODULE_SN],[PART_NO],[START_TIME]) ON [PRIMARY];
CREATE NONCLUSTERED INDEX [IX_PROJ_CODE] ON ' + @testTableName + ' ([PROJ_CODE]) ON [PRIMARY];
CREATE NONCLUSTERED INDEX [IX_PROCESS_ID] ON ' + @testTableName + ' ([PROCESS_ID]) ON [PRIMARY];
CREATE NONCLUSTERED INDEX [IX_LOT_NO] ON ' + @testTableName + ' ([LOT_NO]) ON [PRIMARY];
CREATE NONCLUSTERED INDEX [IX_MODULE_SN] ON ' + @testTableName + ' ([MODULE_SN]) ON [PRIMARY];
CREATE NONCLUSTERED INDEX [IX_PART_NO] ON ' + @testTableName + ' ([PART_NO]) ON [PRIMARY];
--添加数据
INSERT ' + @testTableName + '
SELECT *
FROM PROD_TEST_DET WITH (NOLOCK)
WHERE 1 = 1
AND TEST_TIME >= DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) - 1, 0)
AND TEST_TIME < DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0);
--删除数据
DELETE
FROM PROD_TEST_DET
WHERE 1 = 1
AND TEST_TIME >= DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) - 1, 0)
AND TEST_TIME < DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0);
';
--PRINT @sql;
EXEC SP_EXECUTESQL @sql;
END;
2、根据上面创建的存储过程 SP_BRANCH_TABLE_TEST 添加到job 中每月1号执行一次
添加到job 每月1号执行
3、 以上分表已经完成,下面分表后,查询时匹配到对应的表和跨月查询
如果跨月可以使用UNION ALL
注意开始和结束时间是必选项(可以确定匹配的分表)
/// <summary>
/// 合表 QueryBranchSql
/// </summary>
/// <param name="tablename">表</param>
/// <param name="where">条件</param>
/// <param name="start_time">开始</param>
/// <param name="end_time">结束</param>
/// <returns></returns>
public static string QueryBranchTableSql(string tablename, string where, string start_time, string end_time)
{
DateTime startDate = Convert.ToDateTime(start_time);
DateTime endDate = Convert.ToDateTime(end_time);
string temptable = string.Empty;
string sql = string.Empty;
for (DateTime currentDate = startDate; currentDate <= endDate; currentDate = currentDate.AddMonths(1))
{
DateTime startsyn = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 7, 00, 00).AddDays(-1);
if (startDate >= startsyn)
{
// 当天或昨天
sql += $"SELECT * FROM {tablename}_DAY WITH (NOLOCK) WHERE 1=1 {where} UNION ALL ";
}
else
{
if (currentDate.Year == DateTime.Today.Year && currentDate.Month == DateTime.Today.Month)
{
// 当月
sql += $"SELECT * FROM {tablename} WITH (NOLOCK) WHERE 1=1 {where} UNION ALL ";
}
else
{
if (currentDate.Year == DateTime.Today.Year && currentDate.Month < DateTime.Today.Month)
{
// BranchTable
sql += $"SELECT * FROM {tablename}_{currentDate.ToString("yyyyMM")} WHERE 1=1 {where} UNION ALL ";
}
else
{
sql += $"SELECT TOP 0 * FROM {tablename} WITH (NOLOCK) WHERE 1=1 {where} UNION ALL ";
}
}
}
}
if (!string.IsNullOrEmpty(sql))
{
sql = sql.TrimEnd(" UNION ALL ".ToCharArray());
temptable = string.Format(@"
IF OBJECT_ID('tempdb..#T_BRANCHTABLE') IS NOT NULL
DROP TABLE #T_BRANCHTABLE;
SELECT *
INTO #T_BRANCHTABLE
FROM ({0}) T
WHERE TEST_TIME >= '{1}'
AND TEST_TIME < '{2}';", sql, start_time, end_time);
}
return temptable;
}
4、优化-释放数据库内存
SP_DBCC_SQLSERVE 最好在数据库资源闲置的时候调用
USE [DASHBOARD]
GO
/****** Object: StoredProcedure [dbo].[SP_DBCC_SQLSERVE] Script Date: 2024/7/5 10:15:57 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
--/*********************************************************************************************************
--建立者: DQY 日期﹕2024-04-09
--調用的程序﹕
--說明﹕强制释放数据库内存
--更新記錄﹕
-- 日期 更改人 更新說明
------------------ ------------- --------------------------------------------
-- 2024-04-09 dqy 新增:强制释放数据库内存 【谨用】,在数据吞吐量少的时间段使用,中午12点,凌晨 12点
----*********************************************************************************************************/
--调用 EXECUTE [dbo].[SP_DBCC_SQLSERVE]
ALTER PROCEDURE [dbo].[SP_DBCC_SQLSERVE]
AS
BEGIN
----自动强制释放内存的SQL脚本
DECLARE @TargetMemory DECIMAL(19, 2),
@TotalMemory DECIMAL(19, 2),
@UseMemoryPecent DECIMAL(19, 2);
SELECT @TargetMemory = cntr_value
FROM sys.dm_os_performance_counters
WHERE counter_name = 'Target Server Memory (KB)';
SELECT @TotalMemory = cntr_value
FROM sys.dm_os_performance_counters
WHERE counter_name = 'Total Server Memory (KB)';
SET @UseMemoryPecent = @TotalMemory / @TargetMemory;
SELECT @UseMemoryPecent;
IF @UseMemoryPecent > 0.1
BEGIN
--清除存储过程缓存
DBCC FREEPROCCACHE;
--清除会话缓存
DBCC FREESESSIONCACHE;
--清除系统缓存
DBCC FREESYSTEMCACHE('All');
--清除所有缓存
DBCC DROPCLEANBUFFERS;
--打开高级配置
EXEC sp_configure 'show advanced options', 1;
--设置最大内存值,清除现有缓存空间 20G (根据实际情况设置,具体思路是最大值先调小,然后再设回合适的值。)
EXEC sp_configure 'max server memory', 20480;
EXEC ('RECONFIGURE');
--设置等待时间,强制释放内存需等待一些时间
WAITFOR DELAY '00:01:30';
--重新设置最大内存值 50G 根据实际情况设置,具体思路是最大值先调小,然后再设回合适的值。)
EXEC sp_configure 'max server memory', 51200;
EXEC ('RECONFIGURE');
--关闭高级配置
EXEC sp_configure 'show advanced options', 0;
END;
END
5、每月分表后,视图表跟着更新
更新或创建新的视图
USE [DASHBOARD]
GO
/****** Object: StoredProcedure [dbo].[SP_CREATE_VIEW_PROD_TEST_DET] Script Date: 2024/7/5 10:20:02 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
--/*********************************************************************************************************
--建立者: DQY 日期﹕2024-06-04
--調用的程序﹕
--說明﹕SP_CREATE_VIEW_PROD_TEST_DET
--更新記錄﹕
-- 日期 更改人 更新說明
------------------ ------------- --------------------------------------------
-- 2024-06-04 dqy 每月分表后更新 视图 VIEW_PROD_TEST_DET
----*********************************************************************************************************/
--调用 EXECUTE [dbo].[SP_CREATE_VIEW_PROD_TEST_DET]
ALTER PROCEDURE [dbo].[SP_CREATE_VIEW_PROD_TEST_DET]
AS
BEGIN
DECLARE @sql NVARCHAR(MAX);
DECLARE @viewExists BIT;
-- 检查视图是否存在
IF EXISTS (SELECT * FROM sys.views WHERE name = 'V_PROD_TEST_DET')
SET @viewExists = 1;
ELSE
SET @viewExists = 0;
-- 生成视图定义的SQL脚本
SET @sql = CASE
WHEN @viewExists = 1 THEN N'ALTER VIEW V_PROD_TEST_DET AS '
ELSE N'CREATE VIEW V_PROD_TEST_DET AS '
END +
N'SELECT PROJ_CODE, PROCESS_ID, FFAIL, FAILUREMODE, RESULT, MODULE_SN, START_TIME, TEST_TIME FROM PROD_TEST_DET ' +
N'UNION ALL ';
-- 动态生成每个分表的查询部分
SELECT @sql = @sql +
N'SELECT PROJ_CODE, PROCESS_ID, FFAIL, FAILUREMODE, RESULT, MODULE_SN, START_TIME, TEST_TIME FROM ' +
name + N' UNION ALL '
FROM sys.tables
WHERE name LIKE 'PROD_TEST_DET_%'
AND name <>'PROD_TEST_DET_DAY';
-- 移除最后一个 'UNION ALL'
SET @sql = LEFT(@sql, LEN(@sql) - 10);
--PRINT @sql
-- 执行生成的SQL语句以创建或更新视图
EXEC sp_executesql @sql;
END;
最后和第二步一样 ,把SP_CREATE_VIEW_PROD_TEST_DET 添加到新的job 中,每月一号执行一次,这个视图也更新了