【问题标题】:SQL or PL/pgSQL for the following query to have a better performanceSQL 或 PL/pgSQL 用于以下查询以获得更好的性能
【发布时间】:2021-04-26 08:50:18
【问题描述】:

我正在从 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,但接受的答案对我没有帮助。这让我想知道SQLPL/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;

【问题讨论】:

  • 与您的问题无关,但是:您应该真正避免使用那些可怕的带引号的标识符。他们的麻烦比他们的价值要多得多。 wiki.postgresql.org/wiki/…
  • 感谢您的宝贵建议,@a_horse_with_no_name。然后我需要在 ef core 中找到一种简单的方法来为我执行此操作。

标签: sql-server postgresql full-text-search query-optimization database-migration


【解决方案1】:

我最终得到了以下功能:

我创建了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;

还有SearchGroupQueryPL/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;

另外,如果我做错了或者用错误的方法做错了,请告诉我。

【讨论】:

    猜你喜欢
    • 2015-01-08
    • 1970-01-01
    • 2014-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-16
    • 1970-01-01
    • 2018-09-18
    相关资源
    最近更新 更多