如何解决SQL 或 PL/pgSQL 用于以下查询以获得更好的性能
我正在从 SQL Server 迁移到 PostgreSQL,我在 SQL Server 中有以下存储过程和函数。
ALTER FUNCTION [dbo].[GetContainsSafeText] (@text nvarchar(250))
RETURNS nvarchar(250)
AS
BEGIN
SET @text = ISNULL(NULLIF(ISNULL(@text,''),'""');
SET @text = TRIM(@text);
WHILE (CHARINDEX(' ',@text) > 0)
SET @text = REPLACE(@text,' ',' ');
SET @text = REPLACE(@text,' ',' AND ');
RETURN @text;
END
ALTER PROCEDURE [dbo].[SearchGroupQuery]
@skip int,@count int,@text nvarchar(250),@from datetime2,@location uniqueidentifier,@category uniqueidentifier,@geoLocation geography
AS
BEGIN
SET NOCOUNT ON;
SET @text = dbo.GetContainsSafeText(@text);
WITH LocationTree AS
(
SELECT Id,ParentId
FROM Locations
WHERE Id = @location
UNION ALL
SELECT Locations.Id,Locations.ParentId
FROM LocationTree
JOIN Locations ON LocationTree.Id = Locations.ParentId
)
SELECT *
FROM [groups] g
WHERE (@text = '""' OR
CONTAINS([Description],@text) OR
CONTAINS([Title],@text) OR
Id IN (SELECT GroupId
FROM [Events]
WHERE [Time] >= @from
AND (CONTAINS([Description],@text) OR
CONTAINS([Title],@text))
))
AND (@location IS NULL OR LocationId IN (SELECT Id FROM LocationTree))
AND (@category IS NULL OR Id IN (SELECT GroupId FROM [GroupCategories] cg
WHERE cg.CategoryId = @category))
ORDER BY
Title
OFFSET @skip ROWS FETCH NEXT @count ROWS ONLY;
END
我已将它们迁移到以下位置,但遇到了 control reached end of function without RETURN
。我找到了 this question,但接受的答案对我没有帮助。它只是让我想知道哪一个更好SQL
或PL/pgSQL
。我发现 accepted answer here 很有趣。如果我理解正确,我就不能使用 SQL
但问题是我怎样才能使以下内容更好?此外,添加 return query
并没有解决我的问题。
CREATE OR REPLACE FUNCTION GetContainsSafeText(p_text char varying(250))
RETURNS char varying(250)
AS $$
BEGIN
p_text := coalesce(nullif(coalesce(p_text,'""');
p_text := trim(p_text);
while(POSITION(' ' IN p_text) > 0) loop
p_text := replace(p_text,' ');
END Loop;
p_text := replace(p_text,' & ');
RETURN p_text;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION SearchGroupQuery (
p_skip int,p_count int,p_text char varying(250),p_from timestamp(6),p_location char varying(36),p_category char varying(36),p_geoLocation geography)
RETURNS setof "Groups" AS $$
BEGIN
p_text := GetContainsSafeText(p_text);
return query --<< this was missing the first time
with recursive LocationTree
as
(
select "Id","ParentId" from "Locations" where "Id" = p_location
union all
select "Locations"."Id","Locations"."ParentId" from LocationTree t join "Locations" on t."Id" = "Locations"."ParentId"
)
select
*
from "Groups" g
where
(
p_text = '""""' or
to_tsvector('simple',"Title" || ' ' || "Description") @@ to_tsquery(p_text) or
Id in (
select "GroupId"
from "Events"
where "Time" >= p_from and
to_tsvector('simple',"Title" || ' ' || "Description") @@ to_tsquery(p_text)
)
) and
(
p_location is null or
"LocationId" in (select "Id" from "LocationTree")
) and
(
p_category is null or
"Id" in (
select "GroupId"
from "GroupCategories" cg
where cg."CategoryId" = p_category
)
)
order by "Title"
LIMIT v_count offset p_skip ;
END;
$$ LANGUAGE plpgsql;
解决方法
我最终得到了以下函数:
我制作了 GetContainsSafeText
一条 SQL,因为它不需要准备好执行计划。
CREATE OR REPLACE FUNCTION GetContainsSafeText(p_text char varying(250))
RETURNS char varying(250)
AS $$
select trim(regexp_replace(coalesce(nullif(coalesce(p_text,''),'""'),'\s+',' ','g'));
$$ LANGUAGE SQL;
而且 SearchGroupQuery
是 PL/pgSQL
,因为执行计划似乎很复杂(至少对我而言)。所以很高兴第一次就准备好了,然后继续使用。
CREATE OR REPLACE FUNCTION SearchGroupQuery (
p_skip int,p_count int,p_text char varying(250),p_from timestamp(6),p_location uuid,p_category uuid,p_geoLocation geography)
RETURNS setof "Groups" AS $$
BEGIN
p_text := GetContainsSafeText(p_text);
return query --<< this was missing
with recursive LocationTree
as
(
select "Id","ParentId" from "Locations" where p_location is not null and "Id" = p_location
union all
select "Locations"."Id","Locations"."ParentId" from LocationTree t join "Locations" on t."Id" = "Locations"."ParentId"
)
select
*
from "Groups" g
where
(
p_text = '""""' or
to_tsvector('simple',"Title" || ' ' || "Description") @@ to_tsquery(p_text) or
"Id" in (
select "GroupId"
from "Events"
where "Time" >= p_from and
to_tsvector('simple',"Title" || ' ' || "Description") @@ to_tsquery(p_text)
)
) and
(
p_location is null or
"LocationId" in (select "Id" from LocationTree)
) and
(
p_category is null or
"Id" in (
select "GroupId"
from "GroupCategories" cg
where cg."CategoryId" = p_category
)
)
order by "Title"
LIMIT p_count offset p_skip ;
return;
END;
$$ LANGUAGE plpgsql;
另外,如果我做错了或者使用了错误的resean,请告诉我。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。