有一个由EF创建的查询,它使用索引扫描而不是索引搜索。通过稍微修改查询以不使用参数,可以使用索引查找。索引扫描大约需要三秒钟,而搜索是即时的。
生成的查询(使用索引扫描):
exec sp_executesql N'SELECT TOP (1)
[Extent1].[phone_id] AS [phone_id],
[Extent1].[phone] AS [phone],
[Extent1].[high_usage_flag] AS [high_usage_flag],
[Extent1].[cds_flag] AS [cds_flag],
[Extent1].[never_call_flag] AS [never_call_flag],
[Extent1].[pa_state_dnc_flag] AS [pa_state_dnc_flag],
[Extent1].[ma_state_dnc_flag] AS [ma_state_dnc_flag],
[Extent1].[national_dnc_flag] AS [national_dnc_flag],
[Extent1].[note] AS [note],
[Extent1].[pec_never_call_flag] AS [pec_never_call_flag],
[Extent1].[nicor_dnc_flag] AS [nicor_dnc_flag],
[Extent1].[css_vici_flag] AS [css_vici_flag],
[Extent1].[css_pec_flag] AS [css_pec_flag],
[Extent1].[css_vici_alt_flag] AS [css_vici_alt_flag],
[Extent1].[area_code] AS [area_code],
[Extent1].[phone_type_id] AS [phone_type_id],
[Extent1].[last_answer_date] AS [last_answer_date],
[Extent1].[csr_bad_flag] AS [csr_bad_flag],
[Extent1].[to_process_flag] AS [to_process_flag],
[Extent1].[deleted_date] AS [deleted_date],
[Extent1].[wireless_flag] AS [wireless_flag]
FROM [dbo].[phone] AS [Extent1]
WHERE [Extent1].[phone] = @p__linq__0',N'@p__linq__0 nvarchar(4000)',@p__linq__0=N'555555555'
修改为不使用参数(使用索引查找):
exec sp_executesql N'SELECT TOP (1)
[Extent1].[phone_id] AS [phone_id],
[Extent1].[phone] AS [phone],
[Extent1].[high_usage_flag] AS [high_usage_flag],
[Extent1].[cds_flag] AS [cds_flag],
[Extent1].[never_call_flag] AS [never_call_flag],
[Extent1].[pa_state_dnc_flag] AS [pa_state_dnc_flag],
[Extent1].[ma_state_dnc_flag] AS [ma_state_dnc_flag],
[Extent1].[national_dnc_flag] AS [national_dnc_flag],
[Extent1].[note] AS [note],
[Extent1].[pec_never_call_flag] AS [pec_never_call_flag],
[Extent1].[nicor_dnc_flag] AS [nicor_dnc_flag],
[Extent1].[css_vici_flag] AS [css_vici_flag],
[Extent1].[css_pec_flag] AS [css_pec_flag],
[Extent1].[css_vici_alt_flag] AS [css_vici_alt_flag],
[Extent1].[area_code] AS [area_code],
[Extent1].[phone_type_id] AS [phone_type_id],
[Extent1].[last_answer_date] AS [last_answer_date],
[Extent1].[csr_bad_flag] AS [csr_bad_flag],
[Extent1].[to_process_flag] AS [to_process_flag],
[Extent1].[deleted_date] AS [deleted_date],
[Extent1].[wireless_flag] AS [wireless_flag]
FROM [dbo].[phone] AS [Extent1]
WHERE [Extent1].[phone] = ''5555555555'''
有人可以告诉我这里发生了什么以及如何使Linq使用索引吗?
答案 0 :(得分:4)
问题不是参数嗅探,而是data type precedence。参数键入为NVarchar,列为Varchar。 NVarchar具有更高的数据类型优先级,因此该列将转换为参数类型,并且无法使用索引。
如果已映射参数,EF Core将正确键入参数。因此,您可能缺少模型中的类型配置。 EG
modelBuilder.Entity<Phone>().Property(a => a.Phone).HasColumnType("varchar").HasMaxLength(50);