zoukankan      html  css  js  c++  java
  • SybaseASE系统表的应用

    SybaseASE系统表的应用
    一、问题背景
    在排查江西、湖南地区数字法院系统数据库CPU高和慢SQL问题时,发现系统中有很多简单的全表扫描SQL,原因是一些子表外键没有索引导致。
    添加缺失外健索引成为当务之急。数字法院系统有几十个SMD文档,2000多张表,上万个字段,人工检查SMD文档工作量大,效率低。而sybase的sp_help、sp_helpindex又只能查看单个表的索引情况,没有办法检查整个数据库的索引情况。
     
    二、解决思路
    查阅sp_help和sp_helpindex的源代码发现,可以通过ase的系统表、系统函数来获取到整个数据的建立索引情况,然后通过系统表关联得出没有建立外健索引的字段。
           用到的系统表有:
    1.sysobjects
    系统对象表,每个表、视图、存储过程、触发器等数据库对象都在sysobjects中有一行。
    主要字段如下:
    列名    字段类型    描述
    name    varchar(255)    对象名
    id    int    对象ID
    type    char(2)    对象类型,U:用户表、V:系统表、V:视图
     
    2.syscolumns
    系统列表,每个表、视图中的每一列和过程的每个参数在syscolumns中都有对应的一行。
    主要字段如下:
    列名    字段类型    描述
    id    int     所属表或者过程的id
    colid    smallint    列id
    name    varchar(255)    列名
    type    tinyint    存储类型
    length    int    物理长度
     
    3.sysindexes
    系统索引表,每个聚簇索引、非聚簇索引、没有聚簇索引的表、包含textimage列的表都在sysindexes中有对应的一行。注意:该表中没有索引的key信息,即索引建立在表的哪些字段上。
    主要字段如下:
    列名    字段类型    描述
    id    int    所属表ID或索引ID
    indid    smallint    表内索引id,0:表、1:页锁表聚簇索引、>1:DOL锁表索引、255:textimagelog。表内索引id的范围是1~254,一张表最多能建立254个索引。
    keycnt    smallint    键的个数。取值范围是1~31,复合索引最多能包含31个列。
    name    varchar(255)    表名或索引
    status    smallint    内部系统状态信息
    status2    smallint    内部系统状态信息
    status3    smallint    内部系统状态信息
     
    4.spt_values
    系统内部值表,相当于业务系统中的“单值代码”表。根据type、number 字段 查出其他表中status 对应的name。
    主要字段如下:
    列名    字段类型    描述
    name    varchar(255)    系统内部状态值对应名称
    type    char    系统内部状态类型
    number    int    系统内部状态值
     
       系统函数有:
    1.index_col(obj_name,index_id,key_# [,user_id])
    返回表、视图中索引的列名。
    参数名    描述
    object_name    表名或者视图名
    index_id    表sysindex中indid的值
    key_#    键值顺序。如sysindex中keycnt为3,说明该索引包含3个列,key_#需要依次传入1、2、3,依次获得第一列、第二列、第三列名称
    user_id    object_name的所有者id,可选
     
    2.index_colorder(obj_name,index_id,key_# [,userid])
    返回索引中列的desc/asc顺序。
    参数名    描述
    object_name    表名或者视图名
    index_id    表sysindex中indid的值
    key_#    键值顺序。如sysindex中keycnt为3,说明该索引包含3个列,key_#需要依次传入1、2、3,依次获得第一列、第二列、第三列名称
    user_id    object_name的所有者id,可选
    三、解决步骤
    第一步:创建表T_SYS_TABLE_INDEX 用于存储库中所有表的索引情况,主要字段如下:
    列名    类型    描述
    table_name    varchar(255)    表名
    table_id    int    表id
    index_name    varchar(255)    索引名称
    index_keys    varchar(1024)    索引列
    index_descriptions    varchar(68)    索引描述
    index_created    datetime    索引创建时间
     
     
    第二步: 创建sp_genIndexInfo存储过程,收集单个表的索引信息。
      主要过程为:
    1.循环获取表的所有索引id
    select @indid = min(indid) from sysindexes where id = object_id(@objname) and indid > 0 and indid < 255
     
    while @indid is not NULL
    begin
        ----------------------------
        --获取单个索引的索引键值逻辑
        ----------------------------
        select @lastindid = @indid
        select @indid = NULL
        select @indid = min(indid) from sysindexes where id = object_id(@objname) and indid > @lastindid and indid < 255
    END
     
    2.获取单个索引的索引键值逻辑
    while @i <= 31
        begin
            select @thiskey = index_col(@objname, @indid, @i)
            if (@thiskey is NULL)  
            begin
                goto keysdone
            end
            if @i > 1
            begin
                select @keys = @keys + ", "  
            end
            select @keys = @keys + @thiskey
            select @sorder = index_colorder(@objname, @indid, @i)
            if (@sorder = "DESC")
                select @keys = @keys + " " + @sorder
            select @i = @i + 1
        end
        keysdone:
            set nocount off
     
    3.将索引信息存入T_SYS_TABLE_INDEX表
    insert into T_SYS_TABLE_INDEX
            select @objname,object_id(@objname),name, @keys, @inddesc, maxrowsperpage, fill_factor,
                isnull(res_page_gap,0), crdate,  
                case when (status3 & 8 = 8) then "Local Index"
                     else "Global Index"
                end
                from sysindexes where id = object_id(@objname) and indid = @indid
     
    第三步:循环获取当前库中每一张表的索引信息
    DECLARE @table_name VARCHAR(600)
    DECLARE @table_id INT
    DECLARE @last_table_id INT  
    select @table_id = min(id) from sysobjects where  type = 'U'
    while @table_id is not NULL
    BEGIN
      SELECT @table_name = name FROM sysobjects WHERE type ='U' AND id = @table_id
      EXEC sp_genIndexInfo @table_name
      select @last_table_id = @table_id
      select @table_id = NULL
      select @table_id = min(id),@table_name=name from sysobjects where id > @last_table_id and type = 'U'
    END
     
    第四步:查询未建索引的表和字段
    SELECT db_name() AS dbname,obj1.name AS table_name,cols.name AS col_name  
    FROM syscolumns cols LEFT JOIN sysobjects obj1 ON cols.id = obj1.id  
    WHERE obj1.type = 'U'  
    AND cols.name like 'C_BH_%' AND cols.length = 32
    AND NOT EXISTS (
      SELECT 1 FROM  T_SYS_TABLE_INDEX tis WHERE tis.table_id = obj1.id AND charindex(cols.name,tis.index_keys) >0
    )
    ORDER BY obj1.name desc
     
    四、结果展示
    1、全库已建索引信息
     
    2、全库未建外键索引信息
     
    通过程序或脚本可以将未建索引的外键字段批量生成建立索引脚本。
    五、结论
    Sybase ASE的系统表相当于其他DBMS的数据字典,记录和展示了数据库的元数据信息,利用这些信息DBA和程序员可以做很多的批量处理工作,减少手工劳动,提高效率!

  • 相关阅读:
    使用 asp.net mvc和 jQuery UI 控件包
    ServiceStack.Redis 使用教程
    HTC T8878刷机手册
    Entity Framework CodeFirst 文章汇集
    2011年Mono发展历程
    日志管理实用程序LogExpert
    使用 NuGet 管理项目库
    WCF 4.0路由服务Routing Service
    精进不休 .NET 4.0 (1) asp.net 4.0 新特性之web.config的改进, ViewStateMode, ClientIDMode, EnablePersistedSelection, 控件的其它一些改进
    精进不休 .NET 4.0 (7) ADO.NET Entity Framework 4.0 新特性
  • 原文地址:https://www.cnblogs.com/wangzhen3798/p/6924117.html
Copyright © 2011-2022 走看看