Sql 表中数百万行的查询优化

Sql 表中数百万行的查询优化,sql,database-performance,Sql,Database Performance,我有一个有4列的表 PKID、OutMailID、JobMailingDate、InsertDatetime 这就是将数据插入表的方式 PKID是表的主键 对于JObMailingDate为的单个outMailID,表中有平均值为3的记录 不同的插入日期时间。该表有数百万条记录 我还有很多其他的表,它们有相同的数据,但它们属于不同的类别 现在我想了解一下 1查找InsertDatetime位于参数数据范围之间的所有OutMailID 2一旦我有了OutMailID列表,我想找到所有这些OutMa

我有一个有4列的表

PKID、OutMailID、JobMailingDate、InsertDatetime 这就是将数据插入表的方式 PKID是表的主键 对于JObMailingDate为的单个outMailID,表中有平均值为3的记录 不同的插入日期时间。该表有数百万条记录

我还有很多其他的表,它们有相同的数据,但它们属于不同的类别

现在我想了解一下 1查找InsertDatetime位于参数数据范围之间的所有OutMailID 2一旦我有了OutMailID列表,我想找到所有这些OutMailID的最小InsertDatetime,其中最小日期介于参数1和参数2之间

该表的数据如下所示

Select 1 as PKID,1 as OutMailID,'2010/01/01' as JobMailingDate,'2010/01/01' as InsertDatetime 
UNION ALL

Select 2 as PKID,1 as OutMailID,'2010/01/01' as JobMailingDate,'2010/01/02' as InsertDatetime 
UNION ALL

Select 3 as PKID,1 as OutMailID,'2010/01/01' as JobMailingDate,'2010/01/03' as InsertDatetime 
UNION ALL

Select 4 as PKID,1 as OutMailID,'2010/01/01' as JobMailingDate,'2010/01/04' as InsertDatetime 
Select 
    OutMailID,Min(InsertDatetime)
from 
    Table T
    INNER JOIN 
    (
        Select 
            OutMailID
        from 
            Table 
        Where 
            InsertDatetime Between @Param1 and @Param2
    ) as T1 On (T1.OutMailID = T.outMailID)
Group by 
    OutMailID
Having Min(InsertDatetime) Between Between @Param1 and @Param2
我希望在一个查询中执行上述两个步骤,因此我的查询是这样的

Select 1 as PKID,1 as OutMailID,'2010/01/01' as JobMailingDate,'2010/01/01' as InsertDatetime 
UNION ALL

Select 2 as PKID,1 as OutMailID,'2010/01/01' as JobMailingDate,'2010/01/02' as InsertDatetime 
UNION ALL

Select 3 as PKID,1 as OutMailID,'2010/01/01' as JobMailingDate,'2010/01/03' as InsertDatetime 
UNION ALL

Select 4 as PKID,1 as OutMailID,'2010/01/01' as JobMailingDate,'2010/01/04' as InsertDatetime 
Select 
    OutMailID,Min(InsertDatetime)
from 
    Table T
    INNER JOIN 
    (
        Select 
            OutMailID
        from 
            Table 
        Where 
            InsertDatetime Between @Param1 and @Param2
    ) as T1 On (T1.OutMailID = T.outMailID)
Group by 
    OutMailID
Having Min(InsertDatetime) Between Between @Param1 and @Param2
但这并不好。谁能给我推荐一个好的方法吗

第二个问题是,一旦我有了第一个查询的输出,然后我对其他类别使用相同的上面的查询,以找出该类别中的min InsertDatatime,并且一旦我有了所有类别的所有min日期,那么我必须在所有类别中找到min insert日期

你能帮我一下吗

谢谢 Atul

在with with语句中使用with类似于将所有内容都保存在缓存中以备将来使用的视图,下面是一个示例

with Table1 as (
   Select OutMailID from Table Where InsertDatetime Between @Param1 and @Param2 
),
Table2 as (
   Select 4 as PKID,1 as OutMailID,'2010/01/01' as JobMailingDate,'2010/01/04' as InsertDatetime
)
select * from Table as T
inner join Table1 as T1 on T1.OutMailID = T.outMailID
group by T.OutMailID

这样,您就可以多次重复使用Table1,而无需再次查询它。

此查询是否提供了所需的结果

选择T.OutMailID、MinT.InsertDatetime 来自表T T1.OutMailID=T.OutMailID上的内部联接表T1 以及@Param1和@Param2之间的T2.InsertDatetime
按OutMailID分组我认为表达您的需求的一种更简单的方法是,您需要所有OutMailID,其第一个InsertDateTime在指定的时间段内

事实证明,这种连接根本不是必需的。这是查询的更简单版本:

Select t.OutMailID, Min(InsertDatetime)
from Table T
Group by OutMailID
Having Min(InsertDatetime) Between @Param1 and @Param2;
许多数据库可以利用TableOutMailId、InsertDateTime上的索引进行此查询

现在,这个查询可能不是超高效的,特别是当范围相对于整个数据很小时。因此,坚持上述指标,以下措施可能效果更好:

select t.*
from (select OutMailId, min(InsertDatetime) as min_InsertDatetime
      from table t
      where InsertDatetime Between @Param1 and @Param2
      group by OutMailId
     ) t
where not exists (select 1
                  from table t2
                  where t2.OutMailId = t.OutMailId and
                        t2.InsertDateTime < @Param1
                 );

这应该为第一个子查询使用索引,从而限制ID的数量。它应该对不存在的行使用相同的索引,减少行数。

我将使用with语句来更好地处理此问题,并使用您正在使用的数据库标记您的问题。正如人们可能怀疑的那样,实际的引擎作为性能考虑因素是很重要的。您还应该将涉及的表定义添加为create table语句所有定义为create index的索引以及执行计划添加为纯文本,屏幕截图隐藏了太多的细节,因为我必须对不同的类别执行相同的步骤,所以在with table子句中包含所有3个类别的表会使查询速度非常慢,因为CTE就像一个内联查询,您可以对with table子句执行多个操作,这将一次性执行所有操作,并且不会对性能造成问题,我不确定其他类别是什么,但我会根据我了解的您想要完成的内容更新我的答案