如何在几个表中增强查询性能?

时间:2013-05-23 12:51:23

标签: sql performance informix

我是否应该修改一些关于以下查询的内容(因为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    

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

3 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分: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

该图显示了连接结构。别名a独立地加入bcx; b加入jd上的(查询); ch加入; xy加入;和y加入(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 

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

答案 2 :(得分:1)

  1. 将索引放在需要排序的函数(max,min等)使用的所有连接列和列上。单个表可能有几个这样的列。在这种情况下,请尝试使用它们的组合。
  2. 每次排序时使用PDQ(唯一,排序,分组等)或大型连接。默认情况下,Informix会话内存太低。
  3. 为步骤(1)列中的每个索引更新统计信息为高。
  4. 如果适用,请使用脏读。
  5. 使用执行计划。检查不同方案中的连接顺序和索引用法。
  6. 删除在步骤1中创建的未使用的索引。
  7. 考虑检查您的数据模型:规范化水平降低。如果您希望在短时间内得到结果 - 在理想情况下,连接表的数量必须为1。 现在.. Informix优化器并不理想,可能会出错,特别是在这种情况下。确保生成的执行计划是正确的,并在需要时调整他。