在from子句的select语句中使用from子句的表的优缺点是什么?

时间:2018-09-25 10:18:05

标签: sql sql-server

我有一个查询需要40秒才能执行:

HttpListener Listener = new HttpListener("http", 80);
Listener.Start();
HttpListenerContext ctx;
string s;
byte[] b;
int i;

while (true)
{
    ctx = Listener.GetContext();
    Debug.Print("Serving a page...");
    s = "";
    for (i = 0; i < 500; i++) s += "Hello!"; // a 5KB dumb page
    s += "";
    b = Encoding.UTF8.GetBytes(s);
    ctx.Response.ContentLength64 = b.Length;
    ctx.Response.ContentType = "text/html";
    ctx.Response.OutputStream.Write(b, 0, b.Length);
    ctx.Response.OutputStream.Close();           
    s = null;
    b = null;
    Debug.GC(true);
    Debug.Print("Done with the page.");    
}

在上述查询条件下,tblb.col1 = oc.col1花费了很多时间,然后达到了预期。

因此,我对查询进行了如下优化,只需4秒钟即可执行并给出准确的结果:

    select ID , OPERATOR_NAME, 
JOBS_BULK = ISNULL((select COUNT(distinct REPL_RUN) from Locationn r (NOLOCK) , Batch b (NOLOCK) 
                    where r.FROM_PRO_CODE = b.PRO_CODE and r.FROM_BAT_NUMBER = b.BAT_NUMBER and b.BAT_QUANTITY > 0 and r.ASSIGNED_BULK = o.OPERATOR_NAME and isnull(r.ASSIGNED_BULK_COMPLETE,'N')  = 'N'),0) , 
ITEMS_BULK = ISNULL((select COUNT(*) from Locationn r (NOLOCK) , Batch b (NOLOCK) 
                    where r.FROM_PRO_CODE = b.PRO_CODE and r.FROM_BAT_NUMBER = b.BAT_NUMBER and b.BAT_QUANTITY > 0 and  r.ASSIGNED_BULK = o.OPERATOR_NAME and isnull(r.ASSIGNED_BULK_COMPLETE,'N')  = 'N'),0) , 
JOBS_PICK = ISNULL((select COUNT(distinct REPL_RUN) from Locationn r (NOLOCK) , Batch b (NOLOCK) 
                    where r.FROM_PRO_CODE = b.PRO_CODE and r.FROM_BAT_NUMBER = b.BAT_NUMBER and b.BAT_QUANTITY > 0 and r.ASSIGNED_PICK = o.OPERATOR_NAME and isnull(r.ASSIGNED_PICK_COMPLETE,'N')  = 'N') ,0) ,
ITEMS_PICK = ISNULL((select COUNT(*) from Locationn r (NOLOCK) , Batch b (NOLOCK) 
                    where r.FROM_PRO_CODE = b.PRO_CODE and r.FROM_BAT_NUMBER = b.BAT_NUMBER and b.BAT_QUANTITY > 0 and r.ASSIGNED_PICK = o.OPERATOR_NAME and isnull(r.ASSIGNED_PICK_COMPLETE,'N')  = 'N') ,0) 
from Operatorr o
where  
(ISNULL((select COUNT(*) from Locationn r (NOLOCK) , Batch b (NOLOCK) 
        where ISNULL(ASSIGNED_BULK,' ') <> ' ' and r.FROM_PRO_CODE = b.PRO_CODE and r.FROM_BAT_NUMBER = b.BAT_NUMBER and b.BAT_QUANTITY > 0 and r.ASSIGNED_BULK = o.OPERATOR_NAME and isnull(r.ASSIGNED_BULK_COMPLETE,'N')  = 'N'),0) 
+ ISNULL((select COUNT(*) from Locationn r (NOLOCK) , Batch b (NOLOCK) 
        where ISNULL(ASSIGNED_PICK,' ') <> ' ' and r.FROM_PRO_CODE = b.PRO_CODE and r.FROM_BAT_NUMBER = b.BAT_NUMBER and b.BAT_QUANTITY > 0 and r.ASSIGNED_PICK = o.OPERATOR_NAME and isnull(r.ASSIGNED_PICK_COMPLETE,'N')  = 'N') ,0) ) <> 0

我只是在where子句的select语句中使用了表tblA的联接。 您能告诉我什么是技术原因,为什么第二个查询需要更少的时间来执行?

2 个答案:

答案 0 :(得分:1)

这在黑暗中非常刺眼。开始更改后,我发现您的查询存在更多问题。我已经发表了几条评论,因此请注意,并注意大括号({})中的项目。最后,我看不到为什么需要2个子查询。因为您似乎在第二个查询中检查的是同一件事,而在第一个查询中,tblb.{Some Column}'xyz''abc')的值却不同。

考虑到您只想检查是否有行,也不需要COUNT,可以使用EXISTS。最后,我摆脱了1980年的隐式JOIN语法。

如果这不能为您提供所需的结果,则样本数据和预期结果将是关键,并且您所使用的实际SQL(由于语法错误,您提供的SQL无法使用)。 / p>

SELECT *
FROM tblA A
WHERE EXISTS (SELECT 1
              FROM tblb B
                   JOIN tblc C ON B.Col1 = C.Col1
              WHERE B.{Some Column} IN ('xyz','abc')--The column name is missing in your original query
                                                    --Also in first query you had 'xyz' and 'abc' but 'xyz' both times in your second, which is it?
                AND B.col1 = A.col1);

答案 1 :(得分:1)

您应使用exists编写此类查询。我将从以下内容开始:

select a.*
from tblA a
where exists (select 1
              from tblb b join
                   tblc c
                   on b.col1 = c.col1
              where b.? = 'xyz' and  -- unclear what column this is
                    b.col1 = a.col1
             ) and
       exists (select count (*)
               from tblb b join
                    tblc c
                    on b.col1 = c.col1
               where b.? = 'ABC' and
                     b.col1 = a.col1
              );

影响性能的差异是使用exists。以下是最佳做法:

  • 从不FROM子句中使用逗号。 始终使用正确的,明确的JOIN语法。
  • 使用合格的列名。
  • 提供表别名。

关于为什么您的版本具有不同的性能。一种可能是缓存。另一个是研究执行计划。通常,第一个会更好,但“通常”不会总是“变”。