Sql CTE与条款内履约
好的,SQL Server专家,启动您的分析器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
- 我在应用程序内存中有一个标题列表(大约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)