MySQL执行语句日志分析工具


  由于项目更新了一大版本,过不了多久就会进行一次SQL语句查询的优化任务,由运维部分导出一份历史查询SQL语句日志给开发部门做优化分析工作。以前写过一个日志分析的工具,可以不是很好,所以最近又花了几天时间,完善了这个工具。下面,我来说一下,开发历程:

一、任务分析:

1、工具界面:

2、具体需求:分类统计、忽略参数、调试错误

3、预想效果:参数部分用 ? 代替,工具效果展示:

二、开发编码:(读取(bgWorke),写入)

1、变量设置:

static string resultFile;//日志文件地址
static Dictionary<string, int> Seldic, Updic, Insertdic, Deletedic, Othdic, keysDic;//Dic
static Regex patLike, patEqual, patNumber, patQo, patBE, patManySpace, patOther, patLine, patKeys;//正则
int type = 5;//SQL 语句类型
patLike = new Regex(@"(\s+like\s+)\'(.|\n)+?\'");
patEqual = new Regex(@"=\s*\'(.|\n)+?\'");
patNumber = new Regex(@"\d+");
patQo = new Regex(@"\s+(in)\s*\((\?\,)+");
patBE = new Regex(@"\BETWEEN\s+\'(.)+?\'\s+(AND)\s+\'(.)+?\'");
patManySpace = new Regex(@"\s{2,}");//空格
patOther = new Regex(@"=\s*(''|null)");
patLine = new Regex(@"\d+\s+((Init|Connect|Quit|Statistics)|(Query\s+(COMMIT|BEGIN|Show|SET|GRANT|flush)))", RegexOptions.IgnoreCase);
patKeys = new Regex(@"(\d+\s*(\d{2}\:*)+)\d+\s+(query)");
keysDic = new Dictionary<string, int>();//类型字典
keysDic.Add("s", 1);
keysDic.Add("i", 2);
keysDic.Add("u", 3);
keysDic.Add("d", 4);

2、读取日志:

 private void ReadLog()
        {
            int i = 0;
            StreamReader sr = new StreamReader(resultFile, Encoding.UTF8);
            String line;
            string strSQL = string.Empty;
            int IsNumberCount = 0;//
            int lineNumber = 0;//本行行号
            string Number = string.Empty;
            while ((line = sr.ReadLine()) != null)
            {
                if (patLine.IsMatch(line))
                {
                    continue;
                }
                line = line.ToLower();
                line = line.Replace("\t", "");
                if (line.IndexOf("query") > -1)
                {
                    IsNumberCount += 1;
                    if (lineNumber == 1 && IsNumberCount == 2)
                    {
                        analyzeSQLString(strSQL);
                        IsNumberCount = 1;
                        strSQL = "";
                    }
                    if (lineNumber != 1 && IsNumberCount == 1)
                    {
                        if (!string.IsNullOrEmpty(strSQL))
                        {
                            analyzeSQLString(strSQL);
                            strSQL = "";
                        }
                    }
                    lineNumber = 1;
                    strSQL = patKeys.Replace(line, "").Trim();
                }
                else
                {
                    strSQL += " " + line.Trim();
                    lineNumber++;
                    IsNumberCount = 0;
                }
                i++;
                if (ckDebug.Checked)
                {
                    Thread.Sleep(1);
                    bgWorker.ReportProgress(i, strSQL);
                }
            }
            if (strSQL != "")
            {
                analyzeSQLString(strSQL);
            }
            sr.Close();
            sr.Dispose();
        }

3、语句分析

private void analyzeSQLString(string strSQL)
        {
            keysDic.TryGetValue(Convert.ToString(strSQL[0]), out type);

            if (ckIgnore.Checked)
            {
                if (type == 2)
                {
                    if (strSQL.IndexOf(" values ") > 0)
                    {
                        strSQL = strSQL.Substring(0, strSQL.IndexOf(" values "));
                    }
                }
                else
                {
                    strSQL = patManySpace.Replace(strSQL, " ");//多余空格
                    strSQL = patOther.Replace(strSQL, "=?");//处理 name='' 的情况
                    strSQL = patBE.Replace(strSQL, "between ? and ?");
                    strSQL = patNumber.Replace(strSQL, "?");
                    strSQL = patLike.Replace(strSQL, " like ?");
                    strSQL = patEqual.Replace(strSQL, "=?");
                    strSQL = patQo.Replace(strSQL, "in (");
                }
            }
}

3、写入文件

 private void WriteLog(Dictionary<String, int> data, Dictionary<String, int> sort, StreamWriter sw, int i)
        {
            if (data.Count > 0)
            {
                sort = data.OrderByDescending(o => o.Value).ToDictionary(o => o.Key, p => p.Value);
                foreach (KeyValuePair<string, int> de in sort)
                {
                    sw.Write(de.Value.ToString().PadRight(7, ' ') + "   " + de.Key + "\r\n");
                }
            }
        }

4、最终效果

链接:http://share.weiyun.com/2afd3ddfeb28675b030f5f3f976db161 (密码:7eAR)

三、最后感想:

  说实话,这东西用处不是很大,但是这做这个东西的时候,加深了对正则表达式的学习。

优质内容筛选与推荐>>
1、STL六大组件之——适配器代表大会
2、GB28181实现摄像头语音对讲 - web音频采集调用示例
3、POJ——2449 Remmarguts' Date
4、全排列(我开始怀疑自己的智商了....)
5、Build Virtualbox kernel module after manual upgrade system kernel to latest


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号





    联系我们

    欢迎来到TinyMind。

    关于TinyMind的内容或商务合作、网站建议,举报不良信息等均可联系我们。

    TinyMind客服邮箱:support@tinymind.net.cn