簡體   English   中英

SQL 從另一個表查詢 LIKE

[英]SQL query LIKE from another table

我有一個 SQL 查詢,它從另一個表中獲取值並放入 LIKE %%:

SELECT
  *
FROM
  contacts xa
WHERE
  lower(xa.title) in (
    select
      lower(title)
    from
      contacts con
      inner join ce_campaign_spec_tb camp on lower(con.title) ilike '%' || trim(
        both ' '
        from
          camp.param_val
      ) || '%'
    where
      job_id = '18649b38-ce57-48ba-ac52-9e95085df3f9'
      and param = 'title'
      and relation_id = 1
  )

執行上述查詢需要 2 分鍾。 如何重寫此查詢以更好地執行?

解釋看起來像這樣:

XN Hash IN Join DS_BCAST_INNER  (cost=1183647.16..12653156935.52 rows=2075741 width=801)
  Hash Cond: (lower(("outer".title)::text) = lower(("inner".title)::text))
  ->  XN Seq Scan on contacts xa  (cost=0.00..20757.41 rows=2075741 width=801)
  ->  XN Hash  (cost=1183569.31..1183569.31 rows=31137 width=32)
        ->  XN Nested Loop DS_BCAST_INNER  (cost=427.16..1183569.31 rows=31137 width=32)
              Join Filter: (lower(("outer".title)::text) ~~* (('%'::text || btrim(("inner".param_val)::text, ' '::text)) || '%'::text))
              ->  XN Seq Scan on contacts con  (cost=0.00..20757.41 rows=2075741 width=32)
              ->  XN Materialize  (cost=427.16..427.19 rows=3 width=21)
                    ->  XN Seq Scan on ce_campaign_spec_tb camp  (cost=0.00..331.15 rows=3 width=21)
                          Filter: (((job_id)::text = '18649b38-ce57-48ba-ac52-9e95085df3f9'::text) AND ((relation_id)::text = '1'::text) AND ((param)::text = 'title'::text))
----- Nested Loop Join in the query plan - review the join predicates to avoid Cartesian products -----

EXPLAIN 計划表明最大的成本是:

XN Hash IN Join DS_BCAST_INNER  (cost=1183647.16..12653156935.52 rows=2075741 width=801)

這是整個IN子選擇,有 200 萬行。 此外,它指示DS_BCAST_INNER ,它在Evaluating the query plan - Amazon Redshift上定義為“整個內部表的副本廣播到所有計算節點”。

因此,它基本上是在說它在節點之間發送大量數據,並且每一行都需要通過lower()轉換值,因此很難使查詢高效。

首先,確保表使用適當的分發鍵 ( DISTKEY ) 和排序鍵 ( SORTKEY )。 表被廣播到所有計算節點的事實表明這些表沒有分布在同一個鍵上。 一個好的經驗法則是DISTKEY應該設置為JOINs中最常用的字段。 因此,請檢查contactsce_campaign_spec_tb是否具有與其DISTKEY具有相同值的列,並避免在 JOINed 值中使用計算(即連接原始列而不是從列值計算的值),因為這將避免任何無論如何都可以從使用DISTKEY中受益。

INNER JOIN的開銷也很大,可能是因為連接的復雜性(lower、ilike、trim)。 如果可能,請預先計算此轉換並將其存儲為另一個字段。 如果可以簡化查詢以匹配實際值而無需任何轉換(例如lower()ilike ),那么數據庫可以大大優化查詢。 數據倉庫中的一個重要概念是擁有寬表,這意味着您可以創建可能重復數據的額外列,但更容易查詢。 例如,您可以在每個合同上存儲一個小寫的標題,以避免在每個查詢中將其轉換為小寫。

我也不明白為什么它首先要執行IN子查詢。 它基本上是在說:

SELECT contract where contract IN (SELECT contract where...)

你能去掉那個外面的 select 嗎? 這將避免再次在contracts表中移動。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM