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和程序员可以做很多的批量处理工作,减少手工劳动,提高效率!

  • 相关阅读:
    redis面试题总结
    TP5隐藏index.php
    php四种文件加载语句
    【Redis缓存机制】1.Redis介绍和使用场景
    Linux cpufreq 机制了解 arm
    数码设备发展的核心:分离,互联网营销 狼人:
    豆瓣:“慢公司”,互联网营销 狼人:
    互联网周刊:互联网进化论,互联网营销 狼人:
    怀念中国雅虎:技术文化和惨淡命运,互联网营销 狼人:
    菜鸟玩GAE(Google App Engine)完全指南,互联网营销 狼人:
  • 原文地址:https://www.cnblogs.com/wangzhen3798/p/6924117.html
Copyright © 2011-2022 走看看