我试图在给定索引列值的情况下抓取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...
答案 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)
,true
和x
值如何,都永远不会返回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
也可能会引发性能问题。你需要做一些实验,这种方式在你的情况下是最好的。