带有 NOT IN 子查询的 SELECT INTO 查询需要很长时间/挂起

Posted

技术标签:

【中文标题】带有 NOT IN 子查询的 SELECT INTO 查询需要很长时间/挂起【英文标题】:SELECT INTO query with NOT IN subquery takes a long time / hangs 【发布时间】:2016-11-29 23:46:21 【问题描述】:

问题是此查询挂起或有无限记录,我不知道如何使用 MS ACCESS 修复:

预期的用户输入:

User input Start Date: 1/15/2015
User input End Date: 11/15/2015
User input Upper Data Threshold in kB: 50

源表:

[Master] Table in Access:
Invc Date  Mobile Nbr     PktDtVol   
---------  ----------     --------   
1/15/15   647-409-8206    48kB
2/15/15   647-409-8206    33kB
3/15/15   647-409-8206    8000kB
4/15/15   647-409-8206    20kB
5/15/15   647-409-8206    10kB
6/15/15   647-409-8206    0kB
7/15/15   718-500-2311    3kB
8/15/15   718-500-2311    45kB
9/15/15   718-500-2311    25kB
10/15/15  514-300-3311    33kB
11/15/15  514-300-3311    20kB

[Temp_Table] 中的输出:

Invc Date  Mobile Nbr     PktDtVol    Difference in Days 
---------  ----------     --------   -------------------
7/15/15    718-500-2311    3kB             304
8/15/15    718-500-2311    45kB            304
9/15/15    718-500-2311    25kB            304
10/15/15   514-300-3311    33kB            304
11/15/15   514-300-3311    20kB            304

接受生成上述输出的 SQL 解决方案:

PARAMETERS [Start Date] DateTime, [End Date] DateTime, [Upper Bound Usage in KB] IEEEDouble; 
SELECT m.[Invc Date], m.PktDtVol, m.[Mobile Nbr], DateDiff("d",[Start Date],[End Date]) AS [Difference in days] 
INTO Temp_Table FROM Master AS m 
WHERE (m.[Invc Date]>=[Start Date] And m.[Invc Date])<=[End Date] AND m.[Mobile Nbr] NOT IN 
(SELECT q.[Mobile Nbr] FROM Master AS q WHERE (q.PktDtVol>=[Upper Bound Usage in KB]));

从这里开始,我尝试通过另一个 SQL 语句修改表来创建索引以优化查询,但不起作用:

 CREATE INDEX Index2 ON Master([Ttl Charges])

查询工作正常,源表中有 10 条记录没有挂起,其中多条记录具有预期的输出。但是,当源表中有 56,000 条记录且具有多条记录时,就会出现问题。

【问题讨论】:

@ChristopherD。 - 不,这不是他们想要的。有关详细信息,请参阅他们的earlier question。 大于等于上限?这似乎是对的。我建议小于或等于上限。如果它是上,你有小于。 @Fionnuala q.PktDtVol&gt;=[Upper Bound Usage in KB] 工作正常。成功排除了Upper Bound Usage以上的记录。 【参考方案1】:

[Ttl Charges] 上的索引对您没有任何帮助,但 [PktDtVol] 上的索引可以。我刚刚做了一个 10,000 行的测试,[PktDtVol] 上缺少索引绝对是性能瓶颈:

Indexes:
  none
Time:
  170 seconds (just under 3 minutes)

Indexes:
  [Invc Date]
  [Mobile Number]
Time:
  (same as before)

Indexes:
  [Invc Date]
  [Mobile Number]
  [PktDtVol]
Time:
  36 seconds

如您在评论中提到的那样,为了进一步提高性能,您可以重新编写查询以使用 LEFT JOIN 而不是带有子查询的 NOT IN 子句:

PARAMETERS [Start Date] DateTime, [End Date] DateTime, [Upper Bound Usage in KB] IEEEDouble; 
SELECT 
    [Master].[Invc Date], 
    [Master].PktDtVol, 
    [Master].[Mobile Nbr], 
    DateDiff("d",[Start Date],[End Date]) AS [Difference in days] 
INTO Temp_Table 
FROM 
    [Master] 
    LEFT OUTER JOIN 
    (
        SELECT DISTINCT q.[Mobile Nbr] FROM Master AS q 
        WHERE (q.PktDtVol>=[Upper Bound Usage in KB])
    ) s 
        ON [Master].[Mobile Nbr] = s.[Mobile Nbr] 
WHERE 
    [Master].[Invc Date] >= [Start Date]
        AND [Master].[Invc Date] <= [End Date]
        AND s.[Mobile Nbr] IS NULL;

【讨论】:

我很抱歉,我实际上是想把 [PktDtVol] 放在 CREATE INDEX 的原始帖子中。你是对的,在 [Ttl Charges] 上创建索引没有意义。因此,为我的查询创建该索引仍然没有任何区别。这是实际使用的 CREATE INDEX:CREATE INDEX Index2 ON Master([PktDtVol]) 在表上创建索引后还有什么需要做的吗? 看来下面的可能工作,通过这里的另一个线程:link。当前有效的成功查询在下面的评论中: PARAMETERS [Start Date] DateTime, [End Date] DateTime, [Upper Bound Usage in KB] IEEEDouble; SELECT [Master].[Invc Date], [Master].PktDtVol, [Master].[Mobile Nbr], DateDiff("d",[Start Date],[End Date]) AS [Difference in days] INTO Temp_Table FROM [Master] LEFT OUTER JOIN (SELECT q.[Mobile Nbr] FROM Master AS q WHERE (q.PktDtVol&gt;=[Upper Bound Usage in KB])) s ON [Master].[Mobile Nbr] = s.[Mobile Nbr] WHERE s.[Mobile Nbr] IS NULL;

以上是关于带有 NOT IN 子查询的 SELECT INTO 查询需要很长时间/挂起的主要内容,如果未能解决你的问题,请参考以下文章

为啥第三方包 Autofac 带有两个包?

工厂模式但带有对象参数

使用逻辑 ||带有枚举值

为啥 std::bitset 不带有迭代器?

带有占位符的 FormatMessage

带有 UICollectionViewCell 的可重用 UITableViewCell