【问题标题】:Oracle not using index, Entity Framework & Devart DotConnect for oracleOracle 不使用索引、实体框架和 Devart DotConnect for oracle
【发布时间】:2022-09-23 06:43:39
【问题描述】:

有问题的表有 ~30mio 记录。使用实体框架,我编写了一个 LINQ 查询,如下所示:

dbContext.MyTable.FirstOrDefault(t => t.Col3 == \"BQJCRHHNABKAKU-KBQPJGBKSA-N\");

Devart DotConnect for Oracle 生成:

SELECT
Extent1.COL1,
Extent1.COL2,
Extent1.COL3
FROM MY_TABLE Extent1
WHERE (Extent1.COL3 = :p__linq__0) OR ((Extent1.COL3 IS NULL) AND (:p__linq__0 IS NULL))
FETCH FIRST 1 ROWS ONLY

查询大约需要四分钟,显然是全表扫描。

但是,手工制作这个 SQL:

SELECT
Extent1.COL1,
Extent1.COL2,
Extent1.COL3
FROM MY_TABLE Extent1
WHERE Extent1.COL3 = :p__linq__0
FETCH FIRST 1 ROWS ONLY

在 200 毫秒内返回预期的匹配。

问:为什么会这样?我希望查询优化器注意到如果参数不为空,则右侧部分为假,那么为什么第一个查询没有命中索引?

  • 你能展示解释计划吗?

标签: oracle entity-framework devart


【解决方案1】:

你发布的那个 Linq 是生成那个 SQL 的那个吗?

通常我看到这样的问题是在 Linq 表达式中嵌入 #null 检查时。例如:

var result = dbContext.MyTable.FirstOrDefault(t => searchFilter != null && t.Col3 == searchFilter);

这种类型的检查应该移到 Linq 表达式的外部:

var query = dbContext.MyTable.AsQueryable(); // Assuming no other non-nullable filtering... Otherwise add Where clauses rather than AsQueryable

if (!string.IsNullOrEmpty(searchFilter))
   query = query.Where(t => t.Col3 == searchFilter);

var result = query.FirstOrDefault();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-17
    • 1970-01-01
    • 2017-03-22
    • 1970-01-01
    • 2011-08-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多