如何更快地测试SQL查询?

时间:2014-06-04 14:15:02

标签: sql oracle-sqldeveloper

我获得了这个SQL查询的代码,但是对于我的生活来说无法弄清楚到底发生了什么。我对SQL很陌生,所以非常感谢任何帮助。

 SELECT * 
   FROM ( SELECT rownum as rn
                 , a.* 
            FROM ( SELECT outbound.MSG_ID
                        , outbound.MSG_TYPE
                        , outbound.FROM_ADDR
                        , outbound.TO_ADDR
                        , outbound.EMAIL_SUBJECT
                        , outbound.CREATION_DATE
                        , outbound.MQ_MSG_ID     
                     FROM MESSAGES outbound 
                    WHERE (1 = 1)
                   GROUP BY outbound.MSG_ID
                          , outbound.MSG_TYPE
                          , outbound.FROM_ADDR
                          , outbound.TO_ADDR
                          , outbound.EMAIL_SUBJECT
                          , outbound.CREATION_DATE
                          , outbound.MQ_MSG_ID 
                   ORDER BY CREATION_DATE DESC ) a 
        ) 
   WHERE rn BETWEEN 1 AND 25

我特别理解SELECT rownum as rn, a.* FROM ( ... a ),但我认为这是我编辑查询的地方,只检查1000行(这是我的目标)。现在它正在检查数据库中的所有条目(750,000),我只希望它检查1000进行测试。

谢谢!

2 个答案:

答案 0 :(得分:4)

好吧,让我们开始挑选这个家伙吧。从子查询开始

SELECT outbound.MSG_ID
                        , outbound.MSG_TYPE
                        , outbound.FROM_ADDR
                        , outbound.TO_ADDR
                        , outbound.EMAIL_SUBJECT
                        , outbound.CREATION_DATE
                        , outbound.MQ_MSG_ID     
                     FROM MESSAGES outbound 
                    WHERE (1 = 1)
                   GROUP BY outbound.MSG_ID
                          , outbound.MSG_TYPE
                          , outbound.FROM_ADDR
                          , outbound.TO_ADDR
                          , outbound.EMAIL_SUBJECT
                          , outbound.CREATION_DATE
                          , outbound.MQ_MSG_ID 
                   ORDER BY CREATION_DATE DESC 

在那里发生了什么,子查询是从表MESSAGES中选择msg_id,msg_type等。它对该表进行别名并将其称为出站。 FROM MESSAGES outbound意味着"从MESSAGES获取数据,而是将表调出来。"

现在,你可能会注意到WHERE(1 = 1)条款......这个条款很简单,而且总会发生。有时人们使用WHERE(1 = 1),因为如果选择了某些参数,某个地方的脚本会添加额外的过滤器。现在不用担心。

最后,GROUP BY {blah blah blah}告诉您的数据库重复删除这些数据。它有效地选择了DISTINCT。最后,子查询按Creation_date DESC排序,因此最近出现的消息是所选的消息。如果我不得不猜测,重复数据删除和排序是因为这是一个邮件系统,可能包含基本上重复的记录(比如可能有人怨恨同一个电子邮件),或者因为邮件系统经常是分布式的,并且不强调写入的一致性,而是写速度。我不知道为什么他们需要对这些人进行重复删除,但对你来说重要的是有人认为这是必要的,他们可能是对的。

在子查询之外,您会看到

SELECT rownum as rn
                 , a.* 

子查询所做的一切都标有" a"。请记住早期的​​别名概念。您的整个子查询也有一个别名,它被称为" a"。所以,我们从(" a。*")中选择所有内容,我们也选择了rownumber并调用该rn。最后的where子句说"给我前25行。"

所以...如果你想以这种方式选择1000行(重复数据删除,保持最新等),那么只需将1和25之间的内容更改为1和1000之间的内容。

另一方面,如果您根本不想删除消息,只想要表格的前1000行,那么

    SELECT outbound.MSG_ID
                            , outbound.MSG_TYPE
                            , outbound.FROM_ADDR
                            , outbound.TO_ADDR
                            , outbound.EMAIL_SUBJECT
                            , outbound.CREATION_DATE
                            , outbound.MQ_MSG_ID     
                         FROM MESSAGES outbound 
WHERE ROWNUM <= 1000;

应该做的。

这有帮助吗?

答案 1 :(得分:3)

要回答您的问题,您需要确定您希望限制查询将检查测试的记录子集的时间。

此外,您必须定义测试的目标:您是否希望进行简单检查以确定是否可以执行查询?或者你真的想证明正确性?

如果您只想测试它的执行情况,您可以尽早设置限制,如下所示:

  -- first part of query omitted for brevity
 SELECT TOP 1000 outbound.MSG_ID
      , outbound.MSG_TYPE
      , outbound.FROM_ADDR
      , outbound.TO_ADDR
      , outbound.EMAIL_SUBJECT
      , outbound.CREATION_DATE
      , outbound.MQ_MSG_ID     
  FROM MESSAGES outbound
  -- bottom part of query omitted for brevity

或者,为了获得最快的性能,请限制初始来源:

 -- first part of query omitted for brevity
 SELECT outbound.MSG_ID
      , outbound.MSG_TYPE
      , outbound.FROM_ADDR
      , outbound.TO_ADDR
      , outbound.EMAIL_SUBJECT
      , outbound.CREATION_DATE
      , outbound.MQ_MSG_ID     
  FROM (SELECT TOP 1000 * FROM MESSAGES) outbound
  -- bottom part of query omitted for brevity