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)

三、最后感想:

  說實話,這東西用處不是很大,但是這做這個東西的時候,加深了對正則表達式的學習。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM