我们有这个 MySQL SP,它使用动态 SQL。似乎它在负载下表现不佳。
有可能这个 SP 在负载下变慢是因为它使用动态 SQL 吗?动态 SQL 会导致 MySql 中的性能问题(例如,因为它没有被引擎缓存)吗?
请注意,此 SP 是从其他几个 SP 调用的。它使用临时表将结果传递给父 SP。
CREATE PROCEDURE `CreateAreas`(
_areas varchar(21844),
_comparisonGroup varchar(21844),
_parentArea varchar(21844),
_areaType varchar(21844)
)
BEGIN
-- create temporary table "areas"
-- fill with area ids
create temporary table areas (
id int not null,
code varchar(30),
name varchar(100),
shortName varchar(100),
levelid int not null,
sortOrder int not null,
key (id)
);
-- assumes that only one of the 3 options is valid, areas, comparison group, bounded comparison group
if (_areas is not null) then
set @sql = concat('insert into areas (id, code, name, shortName, levelid, sortOrder) select id, Code, Name, ShortName, LevelID, 0 from GeoArea where Code in (''', replace(_areas, ',', ''','''), ''')');
prepare stmt from @sql;
execute stmt;
deallocate prepare stmt;
elseif (_comparisonGroup is not null) then
-- might not be the most efficient way, but is consistent with the approach above, and we do not expect the list to be long
insert into areas (id, code, name, shortName, levelid, sortOrder)
select GeoAreaID, GeoArea.Code, GeoArea.Name, GeoArea.ShortName, GeoArea.LevelID, SortOrder
from ComparisonGroupGeoAreaLink
INNER JOIN
GeoArea
ON GeoArea.ID = GeoAreaID
where ComparisonGroupID = (select id from ComparisonGroup where Identifier = _comparisonGroup)
and IsMember = 1;
elseif (_parentArea is not null and _areaType is not null) then
-- might not be the most efficient way, but is consistent with the approach above, and we do not expect the list to be long
insert into areas (id, code, name, shortName, levelid, sortOrder)
select a.ID, a.Code, a.Name, a.ShortName, a.LevelID, 0
from (select id from GeoArea where Code = _parentArea) as t
INNER JOIN
GeoAreaLinkCache c
ON
c.ParentAreaID = t.id
inner join GeoArea a
on c.ChildAreaID = a.ID
INNER JOIN
(select id from GeoAreaLevel where Identifier = _areaType) as l
ON
a.LevelID = l.id;
elseif (_areaType is not null) then
-- might not be the most efficient way, but is consistent with the approach above, and we do not expect the list to be long
set @sql = concat('insert into areas (id, code, name, shortName, levelid, sortOrder)
select a.ID, a.Code, a.Name, a.ShortName, a.LevelID, 0
from
(select id from GeoAreaLevel where Identifier in (''', replace(_areaType, ',', ''','''), ''')) l
INNER JOIN
GeoArea a
ON
a.LevelID = l.id');
prepare stmt from @sql;
execute stmt;
deallocate prepare stmt;
end if;
END