• 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的效果就不会明显。

  • 相关阅读:
    Best Time to Buy and Sell Stock III
    Valid Palindrome
    Longest Substring Without Repeating Characters
    Copy List with Random Pointer
    Add Two Numbers
    Recover Binary Search Tree
    Anagrams
    ZigZag Conversion
    Merge k Sorted Lists
    Distinct Subsequences
  • 原文地址:https://www.cnblogs.com/java-oracle/p/5423185.html
Copyright © 2020-2023  润新知