2024年09月01日起,DAS對SQL模板化算法進行逐步優化。
變更背景
慢SQL鏈路和SQL審計鏈路的數據分析中,都依賴對每條SQL進行SQL模板化處理,進而針對相同的模板進行聚合分析。當前這個操作存在一些問題,不能很好處理被截斷的SQL(由于被截斷的位置不確定,有時會導致模板數膨脹,不方便用戶聚類查看)。
變更時間
2024年09月01日起,會逐步對兩類鏈路進行升級。
2024年09月01日更新后,SQL模板化算法的迭代優化,不再另行告知,具體請以接口返回為準。
變更范圍
涉及的數據庫引擎包括:RDS MySQL、RDS PostgreSQL、RDS SQLServer、RDS MariaDB和PolarDB MySQL版。
變更內容
主要優化點:
支持PostgreSQL 中
$$
作為字符串常量定界符(delimiter)的模板化,并修復標識符被錯誤替換成問號的BUG。原始 SQL:
UPDATE "study" SET "name" = 'xiaoming', "ext" = $${"math":90,"english":91}$$ where id=128;
優化前:
UPDATE ? SET ? = ?, ? = $${?:?,?:?}$$ where id=?;
優化后:
UPDATE "study" SET "name"=?,"ext"=? WHERE id=?;
對表名和列名的數字后綴進行替換,減少模板數量。
原始 SQL:
select * from [school_3].[class].[student_25];
優化前:
select * from [school_3].[class].[student_25];
優化后:
SELECT * FROM [school_?].[class].[student_?];
針對 SQLServer,去掉前綴,正確解析 sql_type。
原始 SQL:
(@P0 nvarchar(4000))select id, name from student WHERE name = @P0;
優化前:
模板: (@P0 nvarchar(?))select id, name from student WHERE name = @P0; 解析后的sql_type: p0
優化后:
模板: SELECT id,name FROM student WHERE name=?; 解析后的sql_type: select
保證語法正確的前提下,盡量減少空格,同時保留原始 SQL 中關鍵字的大小寫(不進行大寫轉換)。
原始 SQL:
select `name` from `student` where `id` = 1 and (`name` = 'xiaoming' or `class` = 2);
優化前:
SELECT `name` FROM `student` WHERE `id` = ? AND (`name` = ? OR `class` = ?)
優化后:
SELECT `name` FROM `student` WHERE `id`=? AND (`name`=? OR `class`=?);
完整保留原始 SQL 中的括號。
原始 SQL:
select `name` from `student` where `id` = 1 and (`name` = 'xiaoming');
優化前:
SELECT `name` FROM `student` WHERE `id` = ? AND `name` = ?
優化后:
SELECT `name` FROM `student` WHERE `id`=? AND (`name`=?);
不再將case表達式兩邊的括號轉換為"AS"。
原始 SQL:
select `name`, ( CASE WHEN score > 90 THEN 'A' END ) `grade` from `student`;
優化前:
SELECT `name` , CASE WHEN score > ? THEN ? END AS `grade` FROM `student`
優化后:
SELECT `name`,(CASE WHEN score>? THEN ? END)`grade` FROM `student`;
正確解析"#"之后的內容。
原始 SQL:
select `name`, `#grade` from `student`;
優化前:
SELECT `name`, `
優化后:
SELECT `name`,`#grade` FROM `student`;
處理截斷 SQL 時,丟棄不完整括號內所有內容,減少模板數量。
原始 SQL:
select `name`, `grade` from `student` where id = (select uid from
優化前:
select `name`, `grade` from `student` where id = (select uid from
優化后:
SELECT `name`,`grade` FROM `student` WHERE id=
相似表達式進行合并,避免由于相似表達式個數不同導致的模板膨脹。
原始 SQL:
SELECT CASE WHEN score >= 90 THEN 'A' WHEN score >= 80 THEN 'B' WHEN score >= 70 THEN 'C' WHEN score >= 60 THEN 'D' ELSE 'F' END AS grade FROM students;
優化前:
SELECT CASE WHEN score >= ? THEN ? WHEN score >= ? THEN ? WHEN score >= ? THEN ? WHEN score >= ? THEN ? ELSE ? END AS grade FROM students
優化后:
SELECT CASE WHEN score>=? THEN ? ELSE ? END AS grade FROM students;
變更影響
調用慢SQL的OpenAPI接口DescribeSlowLogs和DescribeSlowLogRecords時,SQLText(SQL語句)對應的SQLHash(SQL模板標識符)的值會變化。
調用SQL洞察的OpenAPI接口GetFullRequestStatResultByInstanceId和GetAsyncErrorRequestListByCode時,SqlId(SQL模板標識符)的值會變化。