添加其他列时,CROSS APPLY查询非常慢

时间:2019-01-12 16:16:33

标签: sql sql-server

我有一个CROSS APPLY查询,它执行得非常快(1秒)。但是,如果我在顶部SELECT中添加某些其他列,查询将运行非常慢(很多分钟)。我看不到是什么原因造成的。

SELECT 
    cs.show_title, im.primaryTitle
FROM
    captive_state cs 
CROSS APPLY
    (SELECT TOP 1 
         imdb.tconst, imdb.titleType, imdb.primaryTitle,
         imdb.genres, imdb.genre1, imdb.genre2, imdb.genre3
     FROM 
         imdb_data imdb 
     WHERE 
         (imdb.primaryTitle LIKE cs.show_title+'%') 
         AND (imdb.titleType like 'tv%' OR imdb.titleType = 'movie')
     ORDER BY 
         imdb.titleType, imdb.tconst DESC) AS im 
WHERE 
    cs.genre1 IS NULL

我仅在添加“类型”字段时才尝试添加/删除各种列-例如genre2(varchar(50))-是否发生缓慢。例如,

SELECT cs.show_title, im.primaryTitle, im.genre2

我希望无论是否添加另外一列,查询的性能基本上都相同。

这里是没有额外列且带有的查询计划。

Est Execution Plan1

Est Execution Plan2

第一个表(cs)具有主键索引和genre1上的索引。第二个表(imdb)具有主键索引和primaryTitle上的索引。

我不确定这是否会引起任何问题。

谢谢您的建议。

4 个答案:

答案 0 :(得分:2)

在第二张屏幕截图中,您正在对imdb_data的主键执行索引扫描。这实际上是在扫描表,就像没有索引一样。

您有两个选择。更改查询以使用imdb_data的索引列,或创建一个新索引来覆盖此查询。

答案 1 :(得分:2)

也许会为顶级CROSS APPLY切换为替代

SELECT TOP 1 WITH TIES 
 cs.show_title, 
 imdb.tconst, imdb.titleType, imdb.primaryTitle,
 imdb.genres, imdb.genre1, imdb.genre2, imdb.genre3
FROM captive_state cs 
JOIN imdb_data imdb 
  ON imdb.primaryTitle LIKE cs.show_title+'%'
 AND (imdb.titleType = 'movie' OR imdb.titleType LIKE 'tv%')
WHERE cs.genre1 IS NULL
ORDER BY ROW_NUMBER() OVER (PARTITION BY cs.show_title ORDER BY imdb.titleType, imdb.tconst DESC)

答案 2 :(得分:0)

您可以包括其他列来索引[imdb_data].[idx_primary_table]. (name is not readable from screenshot)

enter image description here

CREATE INDEX idx_name ON [imdb_data].[idx_primary_table](same cols as in original)
INCLUDE (genre1, genre2, genre3) WITH (DROP_EXISTING=ON)

答案 3 :(得分:0)

尝试将“ join”与“ row_number()”一起使用,而不是“ apply”

select
     dat.primaryTitle
    ,dat.show_title
from (
    select
         imdb.primaryTitle
        ,cs.show_title
        ,row_number() over (partition by cs.show_title order by imdb.titleType, imdb.tconst DESC) as rn
    from imdb_data imdb
    inner join captive_state cs on imdb.primaryTitle LIKE cs.show_title+'%'
    where (imdb.titleType like 'tv%' OR imdb.titleType = 'movie')
    and cs.genre1 IS NULL
) dat
where dat.rn = 1