SQLServer数据库优化学习-总结
背景
各种能力都需要提升.
最近总是遇到SQLServer的问题
趁着周末进行一下学习与提高.
安装与优化
1. 数据库必须安装 64位, 不要安装成32位的版本
2. 数据库的序列号要使用enterprise core 的版本, 不要使用enterprise 的版本, 仅可能使用20个CPU核心.
3. tempdb,要放到性能比较好的硬盘上面,不要将所有的数据库数据文件放到一块硬盘上面. 分散放置,提高性能.
4. 限制SQLServer的内存用量. 专用服务器至少留给服务器10%以上的内存用于系统开销,非专用服务器建议综合考量.
5. 不同业务的数据库实例安装到同一数据库时建议将数据文件分散到不同的磁盘, 避免互相影响.
6. 关闭不必要的软件,尤其是浏览器,不分低效杀毒软件,直播/带广告功能的软件, 避免这些垃圾应用内存泄漏后者是抢占带宽影响性能.
实例级别的优化
1. 修改数据库实例的数据文件增幅, 数据文件默认增幅是1MB次,如果数据库较大,建议至少设置为100MB每次,避免数据库数据量增加较多申请次数.
2. 确认恢复模式, 如果是完整的话 注意磁盘空间的使用. 如果是simple,注意数据库的定时备份与恢复.
3. 确认数据库数据文件的大小与表的数量,表的大小, 如果有表数据量的巨大增幅,需要实时注意, 避免临时表数据量激增.
4. 注意数据库内存和CPU的使用情况, 通过perfmon或者是任务管理器查看服务器的IO资源使用情况, 如果出现瓶颈及时优化.
5. 数据库隔离级别的选用. SQLServer数据库默认是 read_committed隔离级别, 但是读时会添加共享锁. 建议使用 read committed snapshot的方式进行.
如果设置选项READ_COMMITTED_SNAPSHOT为OFF,那么事务在执行读操作时申请共享锁,阻塞其他事务的写操作;
如果设置选项READ_COMMITTED_SNAPSHOT为ON,那么事务在执行读操作时使用Row Versioning,不会申请共享锁,不会阻塞其他事务的写操作;
ALTER DATABASE DATABASE_NAME SET READ_COMMITTED_SNAPSHOT ON;
可以通过 use dataname ; DBCC Useroptions 的方式查看隔离级别.
表与索引级别
1. 要注意核心业务表的大小, 如果表很大,还经常进行大量的插入与删除时尤其需要注意.
2. 注意索引的碎片情况与索引是否有效. 如果缺少特定的索引性能下降会非常严重.
3. 注意数据库的阻塞情况. 如果经常出现阻塞则问题可能会比较严重
4. 适当增加并行度.如果存在大量的大表查询.
5. 定期通过计划任务执行如下处理. 与之前文章一样, 拿过来只要是为了好查询.
6. 可能需要根据数据库表的读写情况设置不一样的 填充因子.
当读写比例大于100:1时,不要设置填充因子,100%填充
当写的次数大于读的次数时,设置50%-70%填充
当读写比例位于两者之间时80%-90%填充
处理方式:
SQLSERVER重新新建所有表的索引.
EXEC SP_MSFOREACHTABLE 'dbcc DBreindex("?")'
SQLSERVER重新收集所有表的统计分析记录.
EXEC SP_UPDATESTATS;
如果是单独表:
ALTER INDEX ALL ON Yourschema.xxxx REBUILD
WITH(FILLFACTOR=80, SORT_IN_TEMPDB=ON ,STATISTICS_NORECOMPUTE = ON )
使用SQL实现对所有表的索引重建
select 'ALTER INDEX ALL ON Yourschema.' + name + ' REBUILD' from sys.objects where schema_id = 5 AND type = 'U'
重建所有的统计信息
select 'update statistics GSCLOUDMSS.' + name + ' with fullscan' from sys.objects where schema_id = 5 AND type = 'U'
注意,需要先将自己的架构对应的id获取到.
另外博客园某博主对数据库聚集索引和非聚集索引的说法:
非聚集索引和聚集索引不一样,
聚集索引索引页的键值指向数据页的具体行;
而非聚集索引不存在数据页,
非聚集索引的索引页中的记录行指向聚集索引或者堆的具体数据页的数据行然后来获取记录,
如果堆或聚集索引还存在溢出的话,从堆或者聚集索引的数据记录还有指向溢出页面的指针。
在非聚集索引中存在聚集索引与堆的优点,看完上文你会发现非聚集索引的数据页记录的行定位指针分别指向聚集索引或堆的行,
但是指向聚集索引的行定位是逻辑值而指向堆的是实际的rid值,逻辑值的好处就是在聚集索引发生分页的情况下,
逻辑值不用改变也就无需更新非聚集索引的指针。
另外关于索引时重建还是重组有如下的说法
REBUILD 操作会重新构建整个索引。它会创建一个全新的索引,删除旧索引,然后将数据从旧索引移到新索引中。
这个过程可以彻底去除碎片并提高索引的性能,因为索引是全新的。
REBUILD 操作通常需要更多的系统资源,包括磁盘空间和处理器时间。
这是一个更重型的操作,适用于大型碎片化严重的索引或需要完全重建的情况。
REORGANIZE 操作会重组索引,尽量减少碎片,而不需要创建全新的索引。
它不会释放多余的磁盘空间,但可以改善索引的性能,尤其是在碎片较小的情况下。
REORGANIZE 操作通常需要较少的系统资源,因为它不涉及创建新索引。
这是一个轻型的操作,适用于较小碎片化或需要更少系统资源的情况。
来源: https://blog.csdn.net/u012190606/article/details/134308148
金蝶官方有一个SQLServer数据库的定时更新索引和统计信息的介绍网站:
SQL Server数据库有时由于长期未做索引重建,导致SQL执行效率下降,
当表的索引碎片率高于30%时,建议重建索引,以提升索引执行效率。
统计信息更新,是为了优化SQL执行计划,避免统计信息过旧导致执行计划不是最优。
根据数据库的大小进行评估,可以定期执行,比如一个月做一次。
来源:金蝶云社区
原文链接:https://vip.kingdee.com/article/183932?productLineId=8
部分SQL信息
1. 查看没有主键的表以及所有表的大小
SELECT
OBJECT_NAME ( object_id ) AS TableName,
SUM( reserved_page_count * 8 ) AS ReservedKB,
SUM( used_page_count * 8 ) AS UsedKB,
SUM( ROW_COUNT * 8 ) AS RowKB
FROM
sys.dm_db_partition_stats
WHERE
OBJECT_NAME ( object_id ) IN ( SELECT NAME FROM sys.TABLES EXCEPT SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_TYPE = 'PRIMARY KEY' )
GROUP BY
OBJECT_NAME ( object_id )
ORDER BY
UsedKB DESC
# 注意业务数据库一定要有主键, 没有主键数据同步会存在问题. 建议处理.
2. 查看没有索引的表情况
SELECT
( SELECT si.rows FROM sysindexes si WHERE si.id = so.id AND indid = 0 ) rows,
so.NAME
FROM
sysobjects so
WHERE
so.xtype = 'U'
AND OBJECTPROPERTY ( so.id, 'TableHasIndex' ) = 0
ORDER BY
1 DESC
# 注意如果业务表很大并且没有索引就是一场灾难
3. 索引碎片情况查看
SELECT
OBJECT_NAME ( sys.indexes.OBJECT_ID ) AS tableName,
sys.indexes.NAME,
page_count,
( page_count * 8.0 / 1024 ) AS 'IndexSizeMB',
avg_page_space_used_in_percent,
avg_fragmentation_in_percent,
record_count,
avg_record_size_in_bytes,
index_type_desc,
fragment_count
FROM
sys.dm_db_index_physical_stats ( db_id ( 'dbname' ), object_id ( 'tablename' ), NULL, NULL, 'sampled' )
JOIN sys.indexes ON sys.indexes.index_id = sys.dm_db_index_physical_stats.index_id
AND sys.indexes.object_id = sys.dm_db_index_physical_stats.object_id
ORDER BY
IndexSizeMB DESC
4. 查看索引与数据的占比
DECLARE @T TABLE
(
[name] VARCHAR(max),
[rows] INT,
reserved VARCHAR(max),
data_size VARCHAR(max),
index_size VARCHAR(max),
unused VARCHAR(max)
)
--将表占用情况存放到表变量
INSERT INTO @T
EXEC sp_MSforeachtable "exec sp_spaceused '?'"
SELECT [name],[rows],reserved,data_size,index_size,unused,
CAST(REPLACE(reserved,'KB','') AS INT)/1024 as reserved_MB,
CAST(REPLACE([data_size],'KB','') AS INT)/1024 as data_size_MB,
CAST(REPLACE([index_size],'KB','') AS INT)/1024 as index_size_MB,
CAST(REPLACE([index_size],'KB','') AS float)/CAST(REPLACE([data_size],'KB','') AS float) as 索引与数据的占比,
CAST(REPLACE([unused],'KB','') AS INT)/1024 as unused_MB
FROM @T
where CAST(REPLACE([data_size],'KB','') AS INT) >0
order by 索引与数据的占比 desc
关于一次索引优化的对比
表行数大约400万, 索引碎片率 99%甚至更高.
xx表 主键索引的碎片率: 99.2084982295355
查询时间验证
select count(1) from xxx. xx
35秒
ALTER INDEX ALL on xxx. xx REBUILD
24min完成
select count(1) from xxx. xx
1秒出结果
重启数据库后 3秒查询出结果
比重建索引之前提升了12倍。
标签:index,数据库,SQLServer,sys,索引,优化,id,size
From: https://www.cnblogs.com/jinanxiaolaohu/p/17873296.html