zoukankan      html  css  js  c++  java
  • SQL Server数据库空间管理 (1)

       数据库经常遇到的问题:

       1)、数据库文件空间用尽  2)、日志文件不停增长 3)、数据库文件无法收缩  4)、自动增长和自动收缩

        本系列就以上面的4个问题入手分析并总结数据库空间的管理方法。

      1、文件的分配方式以及文件空间检查方法

          首先,你在你的数据库中运行sp_spaceused;之后会看到当前数据库的使用空间信息;这个命令也就会将大概的数据库空间信息给你展现出来,并不能查看每个数据文件和日志文件的使用情况;其中对于数据库tempdb来说里面存储的临时数据对象,这个命令是统计不到的。我们知道数据库分为主文件(.mdf)和辅助文件(.ndf);数据的存放按照页和区来存放和管理的,这里有一条命令可以查看具体的页内容:DBCC PAGE (<db id >,<file id >,<page id>,<format id>)我们来运行这个命令前打开跟踪标志(trace flag):

     

          上图使用参数为3的命令,下面我们设置参数为2:看看输出的信息,里面的信息结合Sql Server专题一:索引(上)的内容便可理解,下面的内容其实就将222的数据页内的内容给展现出来了;补充(与下文无关):SQL Server会将总长超过8K的的数据页分开存放,单独放在行溢出(Row-Overflow)页中.

    PAGE: (1:222)
    BUFFER:
    BUF @0x00000001F07A2F40
    bpage = 0x00000001E1068000          bhash = 0x0000000000000000          bpageno = (1:222)
    bdbid = 5                           breferences = 0                     bcputicks = 0
    bsampleCount = 0                    bUse1 = 7102                        bstat = 0x9
    blog = 0x2121215a                   bnext = 0x0000000000000000          
    
    PAGE HEADER:
    Page @0x00000001E1068000
    m_pageId = (1:222)                  m_headerVersion = 1                 m_type = 2
    m_typeFlagBits = 0x0                m_level = 0                         m_flagBits = 0x200
    m_objId (AllocUnitId.idObj) = 34    m_indexId (AllocUnitId.idInd) = 2   Metadata: AllocUnitId = 562949955649536
    Metadata: PartitionId = 562949955649536                                  Metadata: IndexId = 2
    Metadata: ObjectId = 34             m_prevPage = (1:221)                m_nextPage = (1:223)
    pminlen = 10                        m_slotCnt = 137                     m_freeCnt = 38
    m_freeData = 7880                   m_reservedCnt = 0                   m_lsn = (33:400:6)
    m_xactReserved = 0                  m_xdesId = (0:0)                    m_ghostRecCnt = 0
    m_tornBits = -639233702             DB Frag ID = 1                      
    
    Allocation Status
    
    GAM (1:2) = ALLOCATED               SGAM (1:3) = NOT ALLOCATED          PFS (1:1) = 0x40 ALLOCATED   0_PCT_FULL
    DIFF (1:6) = CHANGED                ML (1:7) = NOT MIN_LOGGED           
    
    DATA:
    
    Memory Dump @0x000000000F89A000
    
    000000000F89A000:   01020000 00020200 dd000000 01000a00 df000000  ....................
    000000000F89A014:   01008900 22000000 2600c81e de000000 01000000 
    省略  ............
    000000000F89BFF4:   90015c01 1001be00 86006000                    .........`.
    
    OFFSET TABLE:
    
    Row - Offset                        
    136 (0x88) - 7826 (0x1e92)          
    135 (0x87) - 7792 (0x1e70)          
    134 (0x86) - 7720 (0x1e28)          
    133 (0x85) - 7636 (0x1dd4)               
    125 (0x7d) - 7174 (0x1c06)                
    118 (0x76) - 6802 (0x1a92)          
    省略  ............           
    5 (0x5) - 400 (0x190)               
    4 (0x4) - 348 (0x15c)               
    3 (0x3) - 272 (0x110)               
    2 (0x2) - 190 (0xbe)                
    1 (0x1) - 134 (0x86)                
    0 (0x0) - 96 (0x60)                 
    
    DBCC 执行完毕。

           另一种查看数据库的方法是:在Mangement Studio中选择数据,右键-->报表-->标准报表中查看:这两种统计的方法是不同的;这里是按照区来统计的;上面的sp_spaceused使用的是页统计方法;报表这种方法内部是调用了DBCC SHOWFILESTATS命令,这个命令直接从GAM和SGAM这样的系统分配页面上读取区的分配信息,直接算出数据库文件里面有多少区被分配了;因为SQL Server绝大多数是按照区为单位来分配新的空间的,而系统分配页上的信息是实时更新的,所以这个统计方法比较可靠;在服务器负载很高的情况下也可以执行;所以不推荐sp_spaceused的方法,这种方法还不如查看系统试图(sys.dm_db_partition_stats);

             其实还有一种查看数据空间的方法:DBCC SHOWCONTIG(或者 sys.dm_db_index_physical_stats)这个命令可以统计出你的某张表或者索引用了多少页面、多少区、甚至页面的平均数据量。从这些值你可以算出一张表格占用了多少空间。这个命令的代价恨到,SQL Server会扫描数据库,而扫描的过程是要加锁的;例如sys.dm_db_index_physical_stats就有三种扫描方式。越精确扫描越久。1:LIMITED   2 : SAMPLED  3 : DETAILED这3中方式扫描时间依次增加; 下面为DBCC SHOWCONTIG的统计信息。这种信息对于统计区的使用情况、碎片程度展现比较好。

    DBCC SHOWCONTIG 正在扫描 'DimAccount' 表...
    表: 'DimAccount' (5575058);索引 ID: 1,数据库 ID: 8
    已执行 TABLE 级别的扫描。
    - 扫描页数................................: 2
    - 扫描区数..............................: 1
    - 区切换次数..............................: 0
    - 每个区的平均页数........................: 2.0
    - 扫描密度 [最佳计数:实际计数].......: 100.00% [1:1]
    - 逻辑扫描碎片 ..................: 50.00%
    - 区扫描碎片 ..................: 0.00%
    - 每页的平均可用字节数.....................: 2695.0
    - 平均页密度(满).....................: 66.70%
    DBCC SHOWCONTIG 正在扫描 'DimCurrency' 表...
    表: 'DimCurrency' (21575115);索引 ID: 1,数据库 ID: 8
    已执行 TABLE 级别的扫描。
    - 扫描页数................................: 1
    - 扫描区数..............................: 1
    - 区切换次数..............................: 0
    - 每个区的平均页数........................: 1.0
    - 扫描密度 [最佳计数:实际计数].......: 100.00% [1:1]
    - 逻辑扫描碎片 ..................: 0.00%
    - 区扫描碎片 ..................: 0.00%
    - 每页的平均可用字节数.....................: 3147.0
    - 平均页密度(满).....................: 61.12%
    DBCC SHOWCONTIG 正在扫描 'DimCustomer' 表...
    表: 'DimCustomer' (37575172);索引 ID: 1,数据库 ID: 8
    已执行 TABLE 级别的扫描。
    - 扫描页数................................: 1569
    - 扫描区数..............................: 197
    - 区切换次数..............................: 1238
    - 每个区的平均页数........................: 8.0
    - 扫描密度 [最佳计数:实际计数].......: 15.90% [197:1239]
    - 逻辑扫描碎片 ..................: 75.27%
    - 区扫描碎片 ..................: 3.05%
    - 每页的平均可用字节数.....................: 3037.7
    - 平均页密度(满).....................: 62.47%
      省略……
    DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。

        附加:日志文件 

            我们知道日志文件不是按照页、区来分配和管理的。SQL Server 数据库引擎在内部将每一物理日志文件分成多个虚拟日志单元。虚拟日志单元没有固定大小,并且一个物理日志文件所包含的虚拟日志单元数十部固定的。管理员不能配置或设置虚拟日志单元的大小或数量。但 SQL Server 会尝试控制虚拟日志单元的数目,把它限制在一个合理的范围里。例外情况是,日志文件每字段增长一次,会至少增加一个虚拟日志单元。所以,如果一个日志文件经历了多次自动增长,里面的虚拟日志单元数目会比正常的日志文件多很多,这种情况会影响日志文件管理的效率,以至于影响SQL Server 的启动。事务日志是一种回绕的文件。另外,这里有一篇专门介绍SQL Server的日志的博客。下图为事务日志的工作方式;

       

     

          最后:了解了文件的分配和检查再加上对索引的了解,我们下面就解决第一个和第三个问题:1)、数据库文件空间用尽 。3)、数据库文件无法收缩  

    首先如果出现此种问题,管理员首先会想到将数据文件收缩或者清空。一般有两种命令可以选择: 1】. DBCC SHRINKDATABASE    2】. DBCC SHRINKFILE  由于DBCC SHRINKDATABASE一次运行同时影响所有的文件(包括数据文件和日志文件),使用者不能指定每个文件的目标大小,其结果可能不能达到预期要求。所以建议还是做好规划,对每个文件确定预期目标,然后使用DBCC SHRINKFILE来一个个的处理。一般收缩数据文件的情况会比较多,但是,首先要了解:

              1.文件当期的使用情况,收缩量的大小不可能超过当前文件的空闲空间大小。如果想要压缩数据库的大小,首先就要确认数据文件的确有相应未被使用的空间。如果空间都在使用中,那就要先确认大量占用空间的对象。然后通过归档历史数据,先把空间释放出来;

             2.主数据文件是不能被清空的,能被清空的只有辅助数据文件。

             3.如果要把一个文件组整个清空,要删除分配在这个文件组的对象,或者把他们移到其他文件组上 DBCC SHRINKFILE是不能帮你做到这些的。

            把数据文件里面该清除的数据和对象清除完、确认数据文件有足够的空闲空间后,管理员就可以下 DBCC SHRINKFILE命令来缩小或清空指定文件了。如果是要所有文件,就要填上tearget_size,如果是要清空文件,就选择EMPTYFILE。SQL Server 在做 DBCC SHRINKFILE的时候,会扫描数据文件并对正在读的页面加锁,所以对数据库的性能会有所影响。但是这不是一个独占的行为。在做 DBCC SHRINKFILE的时候,其他用户照样可以对数据库进行读写操作。可以在进程的任何一点停止 DBCC SHRINKFILE操作。

          可是,有时候,明明看到数据文件里面有空间,为啥就是不能压缩或者清空?这是因为数据文件里面虽然有很多空的页面,但是这些页面分散在各个区里,使得整个文件没有很多空区。需要说明的是, DBCC SHRINKFILE做的都是区一级别的动作。他会把使用过的区前移,把没有使用过的区从文件中移除。但是,他不会把一个区里面的空页移除、合并,也不会把页里面的空间移除、合并。所以一个数据库中有很多只使用一个两个页面的区, DBCC SHRINKFILE的效果就不会明显。

  • 相关阅读:
    Vue动态路由配置-router.addRoute
    安装nginx(Centos和docker)
    前后端分离跨域问题解决方案
    centos7 部署 gitlab
    date命令使用方法
    电脑明明安装了模块,但是pycharm还是找不到怎么办
    shell脚本中字符串截取问题
    linux中每登录一个终端,就会自动执行脚本
    腾讯文档中怎么添加二级缩进符号
    查看CPU某一核的情况
  • 原文地址:https://www.cnblogs.com/java-oracle/p/5423185.html
Copyright © 2011-2022 走看看