优化大表上的选择查询?

时间:2016-01-21 19:32:24

标签: java sql oracle optimization query-optimization

我试图在给定索引列值的情况下抓取Oracle数据库中的特定行。我选择索引列后跟整个行数据以便于处理。桌子上大约有1.5亿行,我选择大约100到20万行。我正在使用NVL()替换IN子句中的空值,因为我在JAVA中动态创建这些语句。 IN子句被分成由OR组合在一起的1000个索引块,以避免“列表中的最大表达式数为1000”错误。

您可以想象,此查询需要很长时间才能运行。有什么我可以做的来优化这个查询,但保持相同的功能? (忽略索引值,因为它们只是一个例子)

select INDEX_COLUMN_A, INDEX_COLUMN_B, INDEX_COLUMN_C, TABLE.* from TABLE     
Where (NVL(INDEX_COLUMN_A,''), NVL(INDEX_COLUMN_B,''), NVL(INDEX_COLUMN_C,'')) 
IN (('1','1','1'), ('2','2','2'), ... ('1000','1000','1000')) 
OR (NVL(INDEX_COLUMN_A,''), NVL(INDEX_COLUMN_B,''), NVL(INDEX_COLUMN_C,'')) 
IN (('1001','1001','1001'), ('1002','1002','1002'), ... ('2000','2000','2000')) 
OR...

2 个答案:

答案 0 :(得分:2)

如果nvl()null等测试值中不可能遇到('1','1','1'),您可以安全地避免出现('2000','2000','2000')条件:

select 
  INDEX_COLUMN_A, INDEX_COLUMN_B, INDEX_COLUMN_C, 
  TABLE.* 
from 
  TABLE     
where 
  (INDEX_COLUMN_A, INDEX_COLUMN_B, INDEX_COLUMN_C) 
  in (
    ('1','1','1'), 
    ('2','2','2'), 
    ...,
    ('1000','1000','1000')
  ) 
  OR 
  (INDEX_COLUMN_A, INDEX_COLUMN_B, INDEX_COLUMN_C) 
  in (
    ('1001','1001','1001'), 
    ('1002','1002','1002'),
     ...,
    ('2000','2000','2000')
  ) 
  or
  ...

此外,a in (x1,x2) or a in (x3,x4)之类的表达方式意味着((a=x1 or a=x2) or (a=x3 or a=x4))。在这种情况下的括号可能会被省略而不会产生后果:(a=x1 or a=x2 or a=x3 or a=x4)可能会被in表达式缩短为a in (x1, x2, x3, x4)。因此,初始查询(如果要测试的值中没有空值)与以下内容相同:

select 
  INDEX_COLUMN_A, INDEX_COLUMN_B, INDEX_COLUMN_C, 
  TABLE.* 
from 
  TABLE     
where 
  (INDEX_COLUMN_A, INDEX_COLUMN_B, INDEX_COLUMN_C) 
  in (
    ('1','1','1'), 
    ('2','2','2'), 
    ...,
    ('1000','1000','1000')
    ...,
    ('1001','1001','1001'), 
    ('1002','1002','1002'),
     ...,
    ('2000','2000','2000')
  ) 

P.S。

a in (x,y,z)只是由or连接的一组平等关系的快捷方式:((a=x) or (a=y or (a=z))null永远不等于null,因此表达式{{1}无论null in (x,y,z)truex值如何,都永远不会返回y。因此,如果您确实需要处理z值,则必须将表达式更改为null。但在这种情况下,您无法在表格上使用简单索引。可以构建功能索引来处理这样的表达式,但这是一个非常不同的故事。

<强> P.P.S。 如果列包含数字,则必须根据数字进行测试:而不是nvl(a,'some_never_encountered_value') in (nvl('1', 'some_never_encountered_value'), nvl('2','some_never_encountered_value'),...),您应该使用('1','1','1')

答案 1 :(得分:1)

var workBook = new XSSFWorkbook(); var sheet = workBook.CreateSheet("Sheet1"); var dateStyle = workBook.CreateCellStyle(); var dataFormat = workBook.CreateDataFormat(); dateStyle.DataFormat = dataFormat.GetFormat("M/D/YYYY"); row.CreateCell(0).SetCellValue(item.ModifiedDate.HasValue ? item.ModifiedDate.Value.ToShortDateString(): ""); row.Cells[0].CellStyle = dateStyle; // This will change your cell to date format. 子句中使用or也可以防止使用索引。您可以替换

之类的查询
where

select *
  from table
 where <condition1> or <condition2>

反过来,第二个查询可以产生重复的行(它取决于数据)。为防止重复,您可以使用select * from table where <condition1> union all select * from table where <condition2> 代替union,但使用union all也可能会引发性能问题。你需要做一些实验,这种方式在你的情况下是最好的。