【问题标题】:optimizing a sql query with a large number of records being joined and combined优化一个有大量记录被连接和组合的 sql 查询
【发布时间】:2018-05-20 11:08:55
【问题描述】:

这是我目前的代码,它的作用是:它将具有相同 ID (KEYVADD) 的记录分组,然后根据 having 语句删除它们。

就目前而言,此查询需要 5-10 分钟才能运行,因为审计文件非常大,然后会加入并选择语句。我希望减少这个时间,但我正在努力以一种仍然会返回相同结果的方式来做到这一点。当我尝试将 HAVING 中的内容放入 WHERE 语句时,它只是在状态槽中提取带有空值的订单,而不是时间,而不是一起摆脱 ID。

DECLARE @paramdate DATETIME , @paramdatechar varchar(30),@warehouse int
set @warehouse = 711
set @paramdate= '2018-05-17 12:00:00.000'
set @paramdatechar = CONVERT(varchar(30),@paramdate,121)



exec('  select KEYVADD
    ,min(case when VALUADD=0 then timestmp else null end) as "Status0"
    ,min(case when VALUADD=2 then timestmp else null end) as "Status2"
    ,min(case when VALUADD=4 then timestmp else null end) as "Status4"
    ,min(case when VALUADD=5 then timestmp else null end) as "Status5"
    ,min(case when VALUADD=7 then timestmp else null end) as "Status7"
    ,min(case when VALUADD=8 then timestmp else null end) as "Status8"
    ,min(case when VALUADD=9 then timestmp else null end) as "Status9"
    ,min(nmdoh) as "Customer"
    ,min(c.scscn) as "Container"
    ,min(whsoh) as "Warehouse"
    ,min(preoh) as "Preorder"
    from Audit a
left outer join orderhp h on left(a.KEYVADD,7) = h.ONHOH
left outer join ordercnhpc on h.onhoh = c.onhcn
WHERE 
    whsoh = '''+@warehouse+'''
    and IMGTADD = ''A''
GROUP BY KEYVADD
HAVING(
     (min(case when VALUADD=2 then timestmp else null end) <= '''+ @paramdatechar +''')
        and (
                (
                min(preoh) = ''Y''
                and(  
                    (min(case when VALUADD=4 then timestmp else null end) IS NOT NULL)
                    or   (min(case when VALUADD=5 then timestmp else null end) IS NOT NULL)
                    or   (min(case when VALUADD=7 then timestmp else null end) IS NOT NULL)
                    or   (min(case when VALUADD=8 then timestmp else null end) IS NOT NULL)
                    or   (min(case when VALUADD=9 then timestmp else null end) IS NOT NULL)
                    )
                )
                or
                (
                min(preoh) = ''N''
                )
            )
        and(
                (
                    min(case when VALUADD=7 then timestmp else null end) IS NULL
                    and  min(case when VALUADD=8 then timestmp else null end) IS NULL
                    and  min(case when VALUADD=9 then timestmp else null end) IS NULL
                )
                or
                (
                    min(case when VALUADD=7 then timestmp else null end) >= '''+ @paramdatechar +'''
                    or   min(case when VALUADD=8 then timestmp else null end) >= '''+ @paramdatechar +'''
                    or   min(case when VALUADD=9 then timestmp else null end) >= '''+ @paramdatechar +'''
                )
            )
        ) ') at IBMAS400

结果:

    793841800 2018-05-16 14:46:24.5720000   2018-05-16 13:20:25.2250000 2018-05-16 14:46:36.8530000 NULL    NULL    2018-05-17 13:57:03.0230000 NULL    name 1                  711 N
    793843700 2018-05-16 14:46:24.6410000   2018-05-16 13:20:27.2830000 2018-05-16 14:46:36.8750000 NULL    NULL    2018-05-17 13:57:03.5800000 NULL    name 2                      711 N
    793847800 2018-05-16 14:46:24.7080000   2018-05-16 14:21:21.8600000 2018-05-16 14:46:36.9820000 NULL    NULL    2018-05-17 13:57:04.0010000 NULL    name 3                  711 N
    793849100 2018-05-16 14:46:24.7400000   2018-05-16 14:21:23.5210000 2018-05-16 14:46:37.0430000 NULL    NULL    2018-05-17 13:57:04.3380000 NULL    name 4                      711 N
    793855500 2018-05-16 15:49:01.7590000   2018-05-16 15:21:18.1300000 2018-05-16 15:49:15.5260000 NULL    NULL    2018-05-17 13:57:05.0660000 NULL    name 5                  711 N
    793856100 2018-05-16 15:49:01.7810000   2018-05-16 15:21:19.2200000 2018-05-16 15:49:15.5520000 NULL    NULL    2018-05-17 13:57:05.5630000 NULL    name 6                  711 N
    793865100 2018-05-16 19:54:46.2840000   2018-05-16 16:19:53.7890000 2018-05-16 19:54:57.1080000 NULL    NULL    2018-05-17 13:57:05.9330000 NULL    name 7                      711 N
    793871500 2018-05-16 19:54:46.3350000   2018-05-16 17:20:24.8500000 2018-05-16 19:54:57.1820000 NULL    NULL    2018-05-17 14:07:04.8690000 NULL    name 8                  711 N

我希望有一种方法可以通过更改选择的工作方式或其他方式来减少时间,任何帮助将不胜感激!

【问题讨论】:

  • 我们在谈论多少条记录?一百万?一千万?
  • 目前总数为3100万
  • "left outer join ordercnhpc on h.onhoh = c.onhcn"是否应该是"left outer join ordercnhp c on h.onhoh = c.onhcn"?你能告诉我什么表(VALUADD、nmdoh、whsoh、preoh)在里面吗?表是否有索引,如果有,它们在什么位置?
  • 是的,它应该是这样的。复制过来的时候一定是搞砸了。 VALUADD 在 AUDIT 文件中, nmdoh, whsoh 和 preoh 在 orderhp 中。我编辑了我的最后一条评论,因为我弄清楚了它和它的大约 3100 万条记录。我不好,但索引是什么意思?
  • 我想说如果不将数据放在单独的表或缓存的数据仓库多维数据集中,您将很难减少查询时间。我同意索引也可以工作,但是对于这么多的记录,您可能不得不考虑“我是否需要遍历它们以获得答案,或者我可以计算一次,然后继续插入和计算在较小的数据集上”。此外,Outer 这个词通常表示您想要一条记录,即使连接上的匹配项不存在,这可能是 null 的来源?只是一些想法。

标签: sql ibm-midrange db2-400


【解决方案1】:

https://www.red-gate.com/simple-talk/sql/learn-sql-server/sql-server-index-basics/

你能试试这个,看看它是否更快?另外,如果您在选择中注释掉 c.scscn 字段,为什么还需要加入 ordercnhp 表?

--,min(c.scscn) 作为“容器”

DECLARE @paramdate DATETIME , @paramdatechar varchar(30),@warehouse int
set @warehouse = 711
set @paramdate= '2018-05-17 12:00:00.000'
set @paramdatechar = CONVERT(varchar(30),@paramdate,121)



exec('  select KEYVADD
    ,min(case when VALUADD=0 then timestmp else null end) as "Status0"
    ,min(case when VALUADD=2 then timestmp else null end) as "Status2"
    ,min(case when VALUADD=4 then timestmp else null end) as "Status4"
    ,min(case when VALUADD=5 then timestmp else null end) as "Status5"
    ,min(case when VALUADD=7 then timestmp else null end) as "Status7"
    ,min(case when VALUADD=8 then timestmp else null end) as "Status8"
    ,min(case when VALUADD=9 then timestmp else null end) as "Status9"
    ,min(nmdoh) as "Customer"
    --,min(c.scscn) as "Container"
    ,min(whsoh) as "Warehouse"
    ,min(preoh) as "Preorder"
    from Audit a
left outer join orderhp h on left(a.KEYVADD,7) = h.ONHOH
-- Is the ordercnhp needed?
--left outer join ordercnhp c on h.onhoh = c.onhcn
WHERE 
    whsoh = '''+@warehouse+'''
    and IMGTADD = ''A''
GROUP BY KEYVADD
HAVING(
     (min(case when VALUADD=2 then timestmp else null end) <= '''+ @paramdatechar +''')
        and (
                (
                    min(preoh) = ''N''
                )
                or
                (
                    min(preoh) = ''Y''
                    and(  
                            (min(case when VALUADD in (4,5,7,8,9) then timestmp else null end) IS NOT NULL)
                        )
                )
            )
        and(
                (
                    min(case when VALUADD in (7,8,9) then timestmp else null end) IS NULL
                )
                or
                (
                    min(case when VALUADD in (7,8,9) then timestmp else null end) >= '''+ @paramdatechar +'''
                )
            )
        ) ') at IBMAS400

【讨论】:

  • 这似乎使它更快!谢谢你!
  • 我实际上在不久前删除了它,以测试根本不加入该文件并忘记取消注释它是否更快。所以它应该在那里我只是忘了删除--。
  • 如果您使用 Microsoft SQL,请检查索引和 SQL 查询分析器。 msdn.microsoft.com/en-us/library/ff650689.aspx
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-06-05
  • 1970-01-01
  • 1970-01-01
  • 2012-03-16
  • 2016-10-16
  • 1970-01-01
  • 2016-04-30
相关资源
最近更新 更多