1

关于以下查询,我是否应该修改一些东西(因为它需要很长时间15 seconds!只是为了带来400记录)


 select unique a.regnum  , a.name 
 from re23mmf a , rj82std b , gg7crs c  , rr099stdusr  j , hkcourse  h  , aalt:mms3f x  , aalt:rhcasestudy y 
 where a.regnum = b.regnum and a.regnum = c.regnum 
 and b.term_no = ( select max(d.term_no)   from rj82std d where d.regnum = a.regnum )
 and b.dep_code = j.dep_code and b.study_code = j.study_code 
 and j.start_date <=today and j.end_date >=today  
 and j.emp_num =4324
 and c.crsnum = h.crsnum 
 and h.is_project = 'j' 
 and a.regnum = x.regnum and x.regserial = y.regserial 
 and y.batch_no = ( select max(z.batch_no) from rhcasestudy z where z.regserial = y.regserial )
 and y.case_code <> 5    

请问在写这样的查询时我应该注意什么,关于性能问题?

4

3 回答 3

3

首先检查索引。表上是否有聚集索引或非聚集索引?您可以使用查询中的列创建非聚集索引以提高性能。

于 2013-05-23T13:07:54.283 回答
3

使用 JOIN 表示法,您可以编写:

SELECT UNIQUE a.regnum, a.name 
  FROM re23mmf a
  JOIN rj82std b          ON a.regnum = b.regnum 
  JOIN gg7crs c           ON a.regnum = c.regnum 
  JOIN rr099stdusr j      ON b.dep_code = j.dep_code
                         AND b.study_code = j.study_code 
  JOIN hkcourse h         ON c.crsnum = h.crsnum
  JOIN aalt:mms3f x       ON a.regnum = x.regnum
  JOIN aalt:rhcasestudy y ON x.regserial = y.regserial 
 WHERE b.term_no = (SELECT MAX(d.term_no) FROM rj82std d
                     WHERE d.regnum = a.regnum)
   AND j.start_date <= TODAY AND j.end_date >= TODAY 
   AND j.emp_num = 4324
   AND h.is_project = 'j' 
   AND y.batch_no = (SELECT MAX(z.batch_no) FROM rhcasestudy z
                      WHERE z.regserial = y.regserial)
   AND y.case_code <> 5 

除非我在转录和编辑过程中搞砸了,否则这实际上与原始查询相同。我在 WHERE 子句中保留了单表过滤条件;优化器应该将它们下推到相关的表中,以尽量减少工作量。

如前所述,关键是研究 SET EXPLAIN 的输出并确保没有丢失的索引。确保统计数据是最新的也是一个好主意,也许使用 AUS(自动更新统计数据)。

这将有助于确定表的基数。在 15 秒内生成 400 行可能是可怕的性能(任何表中最多有 400 行),或者可能是出色的性能(最大的表有 40 亿行,每行 2 KiB)。如果没有尺寸信息,很难知道哪个更有可能。

a ----> b ----> j
|       |
|       +-----> d
|
+-----> c ----> h
|
+-----> x ----> y ----> z

该图显示了连接结构。Alias独立地a加入b, c, 和xbjoin to jand to (a sub-query on) d; c加入h; x加入y; 并y加入 (a sub-query on) z

请注意,子查询都是相关的子查询;一般来说,这些效率较低。也许您需要使用子查询,例如:

SELECT d.regnum, MAX(d.term_no) AS max_term_no
  FROM rj82std AS d
 GROUP BY d.regnum

在 FROM 子句中:

SELECT UNIQUE a.regnum, a.name 
  FROM re23mmf a
  JOIN rj82std b          ON a.regnum = b.regnum 
  JOIN gg7crs c           ON a.regnum = c.regnum 
  JOIN rr099stdusr j      ON b.dep_code = j.dep_code
                         AND b.study_code = j.study_code 
  JOIN hkcourse h         ON c.crsnum = h.crsnum
  JOIN aalt:mms3f x       ON a.regnum = x.regnum
  JOIN aalt:rhcasestudy y ON x.regserial = y.regserial
  JOIN (SELECT d.regnum, MAX(d.term_no) AS max_term_no
          FROM rj82std AS d
         GROUP BY d.regnum
       ) AS d1            ON b.regnum = d1.regnum AND b.term_no = d1.max_term_no
  JOIN (SELECT z.regserial, MAX(z.batch_no) AS max_batch_no
          FROM rhcasestudy z
         GROUP BY z.regserial
       ) AS z1            ON y.regserial = z1.regserial
                         AND y.batch_no = z1.max_batch_no
 WHERE j.start_date <= TODAY AND j.end_date >= TODAY 
   AND j.emp_num = 4324
   AND h.is_project = 'j' 
   AND y.case_code <> 5 

这些子查询只需要评估一次,而不是像相关子查询中的每一行。这不是一个保证的胜利,但它通常有很大帮助。

于 2013-05-24T23:37:03.547 回答
1
  1. 将索引放在所有连接的列和需要排序的函数使用的列上(最大、最小等)。一个表可能有几个这样的列。在这种情况下,请尝试使用它们的组合。
  2. 每次进行排序(唯一、排序、分组等)或大连接时都使用 PDQ。默认情况下,Informix 会话内存太低。
  3. 将步骤 (1) 中索引的每个列的统计信息更新为高。
  4. 如果适用,请使用脏读。
  5. 使用执行计划。检查不同场景下的连接顺序和索引使用情况。
  6. 删除在步骤 1 中创建的未使用索引。
  7. 考虑检查您的数据模型:标准化水平降低。如果您期望在短时间内获得结果 - 在理想情况下,连接表的数量必须为 1。现在.. Informix 优化器并不理想,并且可能会出错,尤其是在这种情况下。确保生成的执行计划是正确的,并在需要时对其进行调整。
于 2013-06-12T11:37:03.553 回答