Sql CTE与条款内履约

Sql CTE与条款内履约,sql,sql-server,sql-server-2005,performance,tsql,Sql,Sql Server,Sql Server 2005,Performance,Tsql,好的,SQL Server专家,启动您的分析器 我在应用程序内存中有一个标题列表(大约250个) 我有一个数据库表“books”,包含超过一百万条记录,表中的一列是“title”,类型是nvarchar “books”表还有一列称为“ISBN” books.title不是主键,不是唯一的,而是索引的 所以我想知道哪一个更有效: WITH titles AS (select 'Catcher and the Rye' as Title union all 'Ha

好的,SQL Server专家,启动您的分析器

  • 我在应用程序内存中有一个标题列表(大约250个)
  • 我有一个数据库表“books”,包含超过一百万条记录,表中的一列是“title”,类型是nvarchar
  • “books”表还有一列称为“ISBN”
  • books.title不是主键,不是唯一的,而是索引的
所以我想知道哪一个更有效:

WITH titles AS (select 'Catcher and the Rye' as Title
                union all 'Harry Potter ...'
                ...
                union all 'The World Is Flat')

select ISBN from books, titles where books.title = titles.title;
或:

或:


我希望你有ISBN包括在标题索引,以避免关键查找

CREATE INDEX IX_Titles ON dbo.Books (Title) INCLUDE (ISBN)
现在,IN-vs-JOIN-vs-EXISTs是一个常见的问题。CTE与可读性无关。就我个人而言,我会使用exists,因为你可以通过JOIN获得相同标题的书籍的副本,而人们通常会忘记这一点

;WITH titles AS (select 'Catcher and the Rye' as Title
            union all 'Harry Potter ...'
            ...
            union all 'The World Is Flat')
SELECT
    ISBN 
FROM
    books
WHERE
    EXISTS (SELECT * --or null or = all the same
        FROM
            titles 
        WHERE
            titles .Title = books.Title)
但是,我会考虑的一个结构是强迫“中间物化”在我的搜索标题列表中。也适用于exists或CTE解决方案。这可能对乐观主义者有很大帮助

编辑:正如Steve在评论中提到的,临时表是一个更好的选择

SELECT
    ISBN 
FROM
    (
    SELECT TOP 2000000000
        Title
    FROM
        (select 'Catcher and the Rye' as Title
                union all 'Harry Potter ...'
                ...
                union all 'The World Is Flat'
        ) foo
    ORDER BY
       Title
    ) bar
    JOIN
    books On bar.Title = books.Title


SELECT
    ISBN 
FROM
    books
WHERE
    EXISTS (SELECT * --or null or = all the same
        FROM
            (
            SELECT TOP 2000000000
                Title
            FROM
                (select 'Catcher and the Rye' as Title
                        union all 'Harry Potter ...'
                        ...
                        union all 'The World Is Flat'
                ) foo
            ORDER BY
               Title
            ) bar
        WHERE
            bar.Title = books.Title)

如果选择了这两个选项,请避免使用IN子句,因为列表中的项目数量会增加,查询计划将改变,并很快从潜在的搜索转换为扫描


正常的转折点(我在adventure works上仔细检查过)是,在第65项中,它将计划从搜索更改为扫描。

信任优化器。只有当你从真实的测试中发现,这不是一个明智的选择时,你应该开始考虑哄骗特定的行为。在任何情况下,使用TOP/orderby都是一种非常糟糕的方法,可以通过将查找到的标题插入索引表变量或临时表并连接到该变量或临时表中来完成更容易完成的工作。事实上,未来优化器的改进可能会忽略顶部,因为当它应用于的表表达式少于2000时,它没有语义意义。。。行。@Steve:很好,我忘了临时表/表变量。我会使用临时表进行统计/基数/est。行:不是表变量。TOP/ORDER BY是我不再使用的东西(性能也不确定),但它确实允许进行单个SQL调用。我还希望它能与其他方法相比较。
;WITH titles AS (select 'Catcher and the Rye' as Title
            union all 'Harry Potter ...'
            ...
            union all 'The World Is Flat')
SELECT
    ISBN 
FROM
    books
WHERE
    EXISTS (SELECT * --or null or = all the same
        FROM
            titles 
        WHERE
            titles .Title = books.Title)
SELECT
    ISBN 
FROM
    (
    SELECT TOP 2000000000
        Title
    FROM
        (select 'Catcher and the Rye' as Title
                union all 'Harry Potter ...'
                ...
                union all 'The World Is Flat'
        ) foo
    ORDER BY
       Title
    ) bar
    JOIN
    books On bar.Title = books.Title


SELECT
    ISBN 
FROM
    books
WHERE
    EXISTS (SELECT * --or null or = all the same
        FROM
            (
            SELECT TOP 2000000000
                Title
            FROM
                (select 'Catcher and the Rye' as Title
                        union all 'Harry Potter ...'
                        ...
                        union all 'The World Is Flat'
                ) foo
            ORDER BY
               Title
            ) bar
        WHERE
            bar.Title = books.Title)