为复杂的搜索查询创建索引

时间:2018-06-14 13:27:28

标签: postgresql plpgsql

无法确定如何创建索引以支持复杂查询。我在基本场景中只使用过索引,所以我对如何使用更复杂的索引进行处理感到茫然。

这里使用的SP有助于识别正在使用的类型和列:

CREATE OR REPLACE FUNCTION "SearchListings" (
  "@MakeID"       UUID,
  "@ModelID"      UUID,
  "@TrimID"       UUID,
  "@MinYear"      INTEGER,
  "@MaxYear"      INTEGER,
  "@MinMileage"   INTEGER,
  "@MaxMileage"   INTEGER,
  "@MinPrice"     FLOAT,
  "@MaxPrice"     FLOAT,
  "@Colours"      JSONB,
  "@Keywords"     JSONB,
  "@Distance"     FLOAT,
  "@Region"       VARCHAR(50),
  "@Longitude"    FLOAT,
  "@Latitude"     FLOAT,
  "@MaxMMR"       FLOAT,
  "@SellerType"   VARCHAR(50),
  "@Transmission" VARCHAR(50),
  "@TimeRange"    VARCHAR(25)
)
RETURNS TABLE (
  "ID" UUID
) AS
$func$
BEGIN
  RETURN QUERY SELECT
    li."ID"
  FROM
    "Listings" AS li
  WHERE
    "Status" = 'ACTIVE' AND
    "MakeID" = "@MakeID" AND
    "ModelID" = "@ModelID" AND
    (
      "@TrimID" IS NULL OR
      li."TrimID" = "@TrimID"
    ) AND
    (
      "@MinYear" IS NULL OR
      li."Year" > "@MinYear"
    ) AND
    (
      "@MaxYear" IS NULL OR
      li."Year" < "@MaxYear"
    ) AND
    (
      "@MinMileage" IS NULL OR
      li."Mileage" > "@MinMileage"
    ) AND
    (
      "@MaxMileage" IS NULL OR
      li."Mileage" < "@MaxMileage"
    ) AND
    (
      "@MinPrice" IS NULL OR
      "Price" > "@MinPrice"
    ) AND
    (
      "@MaxPrice" IS NULL OR
      li."Price" < "@MaxPrice"
    ) AND
    (
      "@Colours" IS NULL OR
      (
        "@Colours" IS NOT NULL OR
        "@Colours" ?& ARRAY["Colour"]
      )
    ) AND
    (
      "@Keywords" IS NULL OR
      (
        "@Keywords" IS NOT NULL AND
        "@Keywords" ?& ARRAY(
          SELECT * FROM JSONB_ARRAY_ELEMENTS(li."Keywords"::JSONB)
        )::TEXT[]
      )
    ) AND
    (
      "@MaxMMR" IS NULL OR
      li."MMR" < "@MaxMMR"
    ) AND
    (
      "@Transmission" IS NULL OR
      "@Transmission" = 'AUTOMATIC_MANUAL' OR
      li."Transmission" = "@Transmission"
    ) AND
    (
      "@SellerType" IS NULL OR
      "@SellerType" = 'PRIVATE_DEALER' OR
      li."SellerType" = "@SellerType"
    ) AND
    (
      CASE
        WHEN "@TimeRange" = 'LAST_TWO_NEWER' THEN
          li."PublishedAt" >= (CURRENT_DATE - INTERVAL '2 days')
        WHEN "@TimeRange" = 'ONLY_NEW' THEN
          li."PublishedAt" >= (CURRENT_DATE - INTERVAL '30 minutes')
        ELSE TRUE
      END
    ) AND
    (
      "@Longitude" IS NULL OR
      "@Latitude" IS NULL OR
      "@Distance" IS NULL OR
      ST_DWithin(
        ST_SetSRID(ST_MakePoint("@Longitude", "@Latitude"), 4326),
        ST_SetSRID(li."Location", 4326),
        "@Distance"
      )
    );
END;
$func$ LANGUAGE PLPGSQL;

我应该创建一个包含所有不同列的索引吗?然而,这将排除一些最专业的索引类型,例如我设置的JSONB&GIN索引以及&#34;位置&#34;的GIST空间索引。

所以从本质上说问题是,如何创建复合索引(如果存在)以最大化我的查询性能?

除此之外,您可以建议设计索引的教程或指南吗?那里有很多资源,但它们相对混乱或写得不好。

0 个答案:

没有答案