標籤:
由於項目更新了一大版本,過不了多久就會進行一次SQL語句查詢的最佳化任務,由營運部分匯出一份曆史查詢SQL語句日誌給開發部門做最佳化分析工作。以前寫過一個日誌分析的工具,可以不是很好,所以最近又花了幾天時間,完善了這個工具。下面,我來說一下,開發曆程:
一、任務分析:
1、工具介面:
2、具體需求:分類統計、忽略參數、調試錯誤
3、預想效果:參數部分用 ? 代替,工具效果展示:
二、開發編碼:(讀取(bgWorke),寫入)
1、變數設定:
static string resultFile;//記錄檔地址static Dictionary<string, int> Seldic, Updic, Insertdic, Deletedic, Othdic, keysDic;//Dicstatic 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/b3b2a221231994207b8219cdc685970b (密碼:8p1i)
三、最後感想:
說實話,這東西用處不是很大,但是這做這個東西的時候,加深了對Regex的學習。
MySQL執行語句日誌分析工具