麒麟v10 上部署 TiDB v5.1.2 生产环境优化实践
687
2023-05-28
***如何找出数据库中没有索引的表
在SQL Server数据库的维护中,我们经常需要巡检,找出一些没有索引的表,然后根据实际情况判断是否需要增加索引。下面分享一个脚本,如何找出当前数据库中没有索引的表信息。
/************************************************************************************************************** --脚本名称 : find_without_index_tables.sql --脚本作者 : 潇湘隐者 --创建日期 : 2016-10-27 *************************************************************************************************************** 脚本功能 : 查找数据库中没有任何索引的表,并计算表的行数,用作是否创建索引的一个依据 *************************************************************************************************************** 注意事项 : 需要切换到具体的用户数据库后执行脚本 *************************************************************************************************************** 参考资料 : *************************************************************************************************************** 更新记录 : 2016-10-27:创建此脚本 2020-03-14: 修改脚本,新增SERVER_NAME,DB_NAME ***************************************************************************************************************/ SELECT DISTINCT @@SERVERNAME AS [SERVER_NAME] ,DB_NAME() AS [DB_NAME] ,so.object_id AS [OBJECT_ID] ,SCHEMA_NAME(so.schema_id) +'.' +OBJECT_NAME(so.object_id) AS [TABLE_NAME] ,MAX(dmv.rows) AS [APPROXIMATE_ROWS] ,MAX(d.ColumnCount) AS [COLUMN_COUNT] FROM sys.objects so ( NOLOCK ) JOIN sys.indexes si ( NOLOCK ) ON so.object_id = si.object_id AND so.type IN ( N'U', N'V' ) JOIN sysindexes dmv ( NOLOCK ) ON so.object_id = dmv.id AND si.index_id = dmv.indid FULL OUTER JOIN ( SELECT object_id , COUNT(1) AS ColumnCount FROM sys.columns (NOLOCK) GROUP BY object_id ) d ON d.object_id = so.object_id WHERE so.is_ms_shipped = 0 AND so.object_id NOT IN ( SELECT major_id FROM sys.extended_properties (NOLOCK) WHERE name = N'microsoft_database_tools_support' ) AND INDEXPROPERTY(so.object_id, si.name, 'IsStatistics') = 0 GROUP BY so.schema_id , so.object_id HAVING ( CASE OBJECTPROPERTY(MAX(so.object_id), 'TableHasClustIndex') WHEN 0 THEN COUNT(si.index_id) - 1 ELSE COUNT(si.index_id) END = 0 ) ORDER BY [APPROXIMATE_ROWS] DESC;
上面脚本只能查询当前数据库中没有索引的表,我们知道,生产环境中,一个实例下面往往有多个用户数据库,我们需要采集每个数据库中没有索引的表信息,那么上面脚本明显有点硬伤,所以,重写了这个脚本。
/************************************************************************************************************** --脚本名称 : find_without_index_tables.sql --脚本作者 : 潇湘隐者 --创建日期 : 2016-10-27 *************************************************************************************************************** 脚本功能 : 批量查找实例下面的每个数据库,找出没有任何索引的表 *************************************************************************************************************** 注意事项 : 暂无 *************************************************************************************************************** 参考资料 : *************************************************************************************************************** 更新记录 : 2016-10-27:创建此脚本 2020-03-14: 修改脚本,新增SERVER_NAME,DB_NAME ***************************************************************************************************************/ IF EXISTS (SELECT * FROM tempdb.dbo.sysobjects WHERE id = OBJECT_ID('tempdb.dbo.#Database')) BEGIN DROP TABLE #Database; END CREATE TABLE #Database (database_id INT ,database_name NVARCHAR(128) ); INSERT INTO #Database SELECT database_id, name FROM sys.databases WHERE state_desc='ONLINE' AND name NOT IN ('master','msdb','tempdb','model', 'distribution') DECLARE @database_name NVARCHAR(128); DECLARE @database_id INT; DECLARE @cmdText NVARCHAR(MAX); SET @database_name =''; SET @database_id =1; IF EXISTS (SELECT * FROM tempdb.dbo.sysobjects WHERE id = OBJECT_ID('tempdb.dbo.#TAB_NO_INDEX_INFO')) BEGIN DROP TABLE #TAB_NO_INDEX_INFO; END CREATE TABLE #TAB_NO_INDEX_INFO( [SERVER_NAME] [NVARCHAR](32) NULL, [INSTANCE_NAME] [NVARCHAR](64) NULL, [DATABASE_NAME] [NVARCHAR](32) NULL, [TABLE_NAME] [NVARCHAR](128) NULL, [OBJECT_ID] [INT] NULL, [APPROXIMATE_ROWS] [INT] NULL, [COLUMN_COUNT] [INT] NULL ); WHILE(1=1) BEGIN SELECT TOP 1 @database_id = database_id , @database_name = database_name FROM #Database WHERE database_id > @database_id -- next database_name greater than @database_id ORDER BY database_id -- database_id order -- exit loop if no more name greater than the last one used If @@rowcount = 0 Break SET @cmdText='USE ' + @database_name +'; --GO INSERT INTO #TAB_NO_INDEX_INFO ( SERVER_NAME , INSTANCE_NAME , DATABASE_NAME , TABLE_NAME , OBJECT_ID , APPROXIMATE_ROWS , COLUMN_COUNT ) SELECT DISTINCT CAST(SERVERPROPERTY(''MachineName'') AS NVARCHAR(32)) AS [SERVER_NAME] , @@SERVICENAME AS [INSTANCE_NAME] , DB_NAME() AS [DATABASE_NAME] , SCHEMA_NAME(so.schema_id)+ ''.'' + OBJECT_NAME(so.object_id) AS [TABLE_NAME] , so.object_id AS [OBJECT_ID] , MAX(dmv.rows) AS [APPROXIMATE_ROWS] , MAX(d.ColumnCount) AS [COLUMN_COUNT] FROM sys.objects so ( NOLOCK ) JOIN sys.indexes si ( NOLOCK ) ON so.object_id = si.object_id AND so.type IN ( N''U'', N''V'' ) JOIN sysindexes dmv ( NOLOCK ) ON so.object_id = dmv.id AND si.index_id = dmv.indid FULL OUTER JOIN ( SELECT object_id , COUNT(1) AS ColumnCount FROM sys.columns (NOLOCK) GROUP BY object_id ) d ON d.object_id = so.object_id WHERE so.is_ms_shipped = 0 AND so.object_id NOT IN ( SELECT major_id FROM sys.extended_properties (NOLOCK) WHERE name = N''microsoft_database_tools_support'' ) AND INDEXPROPERTY(so.object_id, si.name, ''IsStatistics'') = 0 GROUP BY so.schema_id , so.object_id HAVING ( CASE OBJECTPROPERTY(MAX(so.object_id), ''TableHasClustIndex'') WHEN 0 THEN COUNT(si.index_id) - 1 ELSE COUNT(si.index_id) END = 0 ) ORDER BY [APPROXIMATE_ROWS] DESC; ' PRINT @cmdText; EXEC ( @cmdText); --EXEC SP_EXECUTESQL @cmdText, N'@database_name NVARCHAR(32)',@database_name Delete Db From #Database Db WHERE database_id=@database_id; END SELECT * FROM #TAB_NO_INDEX_INFO ORDER BY APPROXIMATE_ROWS DESC; --找出数据量超过1000行没有索引信息的表 SELECT * FROM #TAB_NO_INDEX_INFO WHERE APPROXIMATE_ROWS > 1000 ORDER BY APPROXIMATE_ROWS DESC
当你维护了很多***数据库时,使用上面脚本到每台SQL Server实例上跑一次,也是一件非常麻烦耗时的事情,所以还是需要自动化作业处理,定时使用Python脚本去每台SQL Server实例上采集数据存储下来,然后DBA只需做好两件事情:监控采集数据和分析处理数据。这里就不贴Python脚本了,其实就是循环所有SQL Server实例,运行上面脚本,将采集到的相关数据存储起来。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。