CASE条款上的ORDER BY可以更快吗?

时间:2012-09-20 22:35:17

标签: sql performance sql-server-2008 sql-order-by

我从一张约有3.5亿条记录的表中选择结果,并且运行速度非常慢 - 大约10分钟。罪魁祸首似乎是 ORDER BY ,就像我删除它一样,查询只需要一点时间。这是要点:

SELECT TOP 100
    (columns snipped)
FROM (
    SELECT 
        CASE WHEN (e2.ID IS NULL) THEN
            CAST(0 AS BIT) ELSE CAST(1 AS BIT) END AS RecordExists,
        (columns snipped)
    FROM dbo.Files AS e1
    LEFT OUTER JOIN dbo.Records AS e2 ON e1.FID = e2.FID
)  AS p1
ORDER BY p1.RecordExists

基本上,我按照 Files 是否有相应的记录来排序结果,因为那些不需要先处理。我可以使用 WHERE 子句运行两个查询,但如果可能的话,我宁愿在单个查询中执行此操作。

有什么方法可以加快速度吗?

4 个答案:

答案 0 :(得分:2)

尝试使用此表单

SELECT TOP(100) *
FROM (
    SELECT TOP(100)
        0 AS RecordExists
        --,(columns snipped)
    FROM dbo.Files AS e1
    WHERE NOT EXISTS (SELECT * FROM dbo.Records e2 WHERE e1.FID = e2.FID)
    ORDER BY SecondaryOrderColumn
) X
UNION ALL
SELECT * FROM (
    SELECT TOP(100)
        1 AS RecordExists
        --,(columns snipped)
    FROM dbo.Files AS e1
    INNER JOIN dbo.Records AS e2 ON e1.FID = e2.FID
    ORDER BY SecondaryOrderColumn
) X
ORDER BY SecondaryOrderColumn

关键指标:
记录(FID)
文件(FID,SecondaryOrdercolumn)

答案 1 :(得分:1)

它之所以慢得多是因为它没有order by子句,实际上是一个非常不同的查询。

使用order by子句: 查找整个3.5亿行中的所有匹配记录。然后对它们进行排序。

没有order by子句: 找到前100个匹配的记录。停止。

答案 2 :(得分:0)

在SQL Server中,null值的整理低于域中的任何值。鉴于这两个表:

create table dbo.foo
(
  id   int         not null identity(1,1) primary key clustered ,
  name varchar(32) not null unique nonclustered ,
)

insert dbo.foo ( name ) values ( 'alpha' )
insert dbo.foo ( name ) values ( 'bravo' )
insert dbo.foo ( name ) values ( 'charlie' )
insert dbo.foo ( name ) values ( 'delta' )
insert dbo.foo ( name ) values ( 'echo' )
insert dbo.foo ( name ) values ( 'foxtrot' )
go

create table dbo.bar
(
  id     int         not null identity(1,1) primary key clustered ,
  foo_id int             null foreign key references dbo.foo(id) ,
  name   varchar(32) not null unique nonclustered ,
)
go
insert dbo.bar( foo_id , name ) values( 1 , 'golf' )
insert dbo.bar( foo_id , name ) values( 5 , 'hotel' )
insert dbo.bar( foo_id , name ) values( 3 , 'india' )
insert dbo.bar( foo_id , name ) values( 5 , 'juliet' )
insert dbo.bar( foo_id , name ) values( 6 , 'kilo' )
go

查询

select *
from      dbo.foo foo
left join dbo.bar bar on bar.foo_id = foo.id
order by bar.foo_id, foo.id

产生以下结果集:

id name    id   foo_id name
-- ------- ---- ------ -------
2  bravo   NULL NULL   NULL
4  delta   NULL NULL   NULL
1  alpha   1    1      golf
3  charlie 3    3      india
5  echo    2    5      hotel
5  echo    4    5      juliet
6  foxtrot 5    6      kilo

(7 row(s) affected)

应该允许查询优化器使用合适的索引(如果存在);但是,它确实保证,而不是使用任何此类索引。

答案 3 :(得分:0)

你能试试吗?

SELECT TOP 100
    (columns snipped)
FROM dbo.Files AS e1
LEFT OUTER JOIN dbo.Records AS e2 ON e1.FID = e2.FID
ORDER BY e2.ID ASC

这应该会给你e2.ID首先为空的位置。另外,请确保将Records.ID编入索引。这应该给你你想要的订单。