【问题标题】:Use index hint and join hint使用索引提示和连接提示
【发布时间】:2015-03-24 15:09:58
【问题描述】:

(询问:tuning in sql server - views。抱歉,我需要查看我的帖子)。

我需要在连接中添加提示(在连接时强制使用 ID 上的索引), 并在选择(对于 where 子句的名称强制使用索引),如本文中提到的最后一个查询。 我不知道正确连接(用于调整)的正确语法是什么,强制索引的正确语法是什么,where 子句将使用它,而我从视图中选择。

我在sql server 2012中创建了一个视图,如:

create myview as
select mytable2.name
from mytable1 t1
join myTable2 t2
on t1.id = t2.id

我希望连接 table1 和 table2 将具有正确的索引 (id),但是当我这样做时:

select * from myview
where name = 'abcd'

我希望最后一个选择将带有列“名称”的索引。

正如我所描述的,在带有提示(调整)的 sql server 中,运行得最好的正确语法是什么?

我想强制使用索引仅用于连接目的(列 = id),并在执行时强制使用索引名称:

select name from myview 
where name = 'abcd'.

类似

create myview as
select mytable2.name
/* index hint name on  column name */
from mytable1 t1
join myTable2 t2
/* index hint name on  column id - just for join */
on t1.id = t2.id

我不想强迫使用视图的最终用户在执行视图时添加提示 - 只需将视图作为他的视图,并提供适当的索引提示。 (或者,如果不可能 - 我该怎么做)。

需要样品,请。

我有这样一个简单的视图(无论表格是基于什么...它非常适合我工作的公司。这是 Microsoft Dynamics AX 2012+ 一些额外的表格)。

create view [dbo].[splSqlAltItemsView]
as
select i_orig.dataareaid, id_orig.inventsiteid, i_orig.itemid, i_alt.itemid altItemId,
orig_item.minTollerance, orig_item.maxTollerance
from 
(
select orig_item.recid,
c_grade.value as grade,
c_materialFamily.value as MaterialFamily,
c_shape.value as shape,
c_thickness.value as thickness,
convert(real, isnull(c_minTollerance.value, 0.00)) as minTollerance,
convert(real, isnull(c_maxTollerance.value, 0.00)) as maxTollerance
from
(select e0.recid
from ECORESPRODUCT e0
where e0.recid in 
(
select productid
from CMAPRODUCTATTRIBUTEVALUES c0
where name in ('Grade', 'Material Family', 'Shape', 'Thickness')
and productid > 0
group by productid
having count(1) = 4
)) orig_item
join CMAPRODUCTATTRIBUTEVALUES c_grade
on c_grade.PRODUCTID = orig_item.RECID
and c_grade.name = 'Grade'
join CMAPRODUCTATTRIBUTEVALUES c_materialFamily
on c_materialFamily.PRODUCTID = orig_item.RECID
and c_materialFamily.name = 'Material Family'
join CMAPRODUCTATTRIBUTEVALUES c_shape
on c_shape.PRODUCTID = orig_item.RECID
and c_shape.name = 'Shape'
join CMAPRODUCTATTRIBUTEVALUES c_thickness
on c_thickness.PRODUCTID = orig_item.RECID
and c_thickness.name = 'Thickness'
left join CMAPRODUCTATTRIBUTEVALUES c_minTollerance
on c_minTollerance.PRODUCTID = orig_item.RECID
and c_minTollerance.name = 'Min Tollerance'
left join CMAPRODUCTATTRIBUTEVALUES c_maxTollerance
on c_minTollerance.PRODUCTID = orig_item.RECID
and c_minTollerance.name = 'Max Tollerance'
) orig_item
join 
(select alt_item.recid,
c_grade.value as grade,
c_materialFamily.value as MaterialFamily,
c_shape.value as shape,
c_thickness.value as thickness,
convert(real, isnull(c_minTollerance.value, 0.00)) as minTollerance,
convert(real, isnull(c_maxTollerance.value, 0.00)) as maxTollerance
from
(select e0.recid
from ECORESPRODUCT e0
where e0.recid in 
(
select productid
from CMAPRODUCTATTRIBUTEVALUES c0
where name in ('Grade', 'Material Family', 'Shape', 'Thickness')
and productid > 0
group by productid
having count(1) = 4
)) alt_item
join CMAPRODUCTATTRIBUTEVALUES c_grade
on c_grade.PRODUCTID = alt_item.RECID
and c_grade.name = 'Grade'
join CMAPRODUCTATTRIBUTEVALUES c_materialFamily
on c_materialFamily.PRODUCTID = alt_item.RECID
and c_materialFamily.name = 'Material Family'
join CMAPRODUCTATTRIBUTEVALUES c_shape
on c_shape.PRODUCTID = alt_item.RECID
and c_shape.name = 'Shape'
join CMAPRODUCTATTRIBUTEVALUES c_thickness
on c_thickness.PRODUCTID = alt_item.RECID
and c_thickness.name = 'Thickness'
left join CMAPRODUCTATTRIBUTEVALUES c_minTollerance
on c_minTollerance.PRODUCTID = alt_item.RECID
and c_minTollerance.name = 'Min Tollerance'
left join CMAPRODUCTATTRIBUTEVALUES c_maxTollerance
on c_minTollerance.PRODUCTID = alt_item.RECID
and c_minTollerance.name = 'Max Tollerance'
) alt_item 
on alt_item.grade = orig_item.grade
and alt_item.MaterialFamily = orig_item.MaterialFamily
and alt_item.shape = orig_item.shape
and (alt_item.thickness between orig_item.thickness - orig_item.minTollerance and orig_item.thickness + orig_item.maxTollerance or
  orig_item.thickness between alt_item.thickness - alt_item.minTollerance and alt_item.thickness + alt_item.maxTollerance)
join inventtable i_orig
on i_orig.product = orig_item.recid
join InventItemInventSetup is_orig
on is_orig.dataareaid = i_orig.dataareaid 
and is_orig.itemid = i_orig.itemid 
and is_orig.inventdimid = 'AllBlank'
join InventDim id_orig
on id_orig.DATAAREAID = is_orig.DATAAREAID
and id_orig.inventdimid = is_orig.inventdimiddefault
join inventtable i_alt
on i_alt.product = alt_item.recid
and i_alt.DATAAREAID = i_orig.DATAAREAID
join InventItemInventSetup is_alt
on is_alt.dataareaid = i_alt.dataareaid 
and is_alt.itemid = i_alt.itemid 
and is_alt.inventdimid = 'AllBlank'
join InventDim id_alt
on id_alt.DATAAREAID = is_alt.DATAAREAID
and id_alt.inventdimid = is_alt.inventdimiddefault
and id_alt.inventsiteid = id_orig.inventsiteid

当我这样做时:

select * from splSqlAltItemsView
where itemid = '12345'

耗费大量时间,甚至 inventTable 在 itemid 上都有索引。

当我这样做时:

 select * from splSqlAltItemsView

视图会运行几秒钟。

【问题讨论】:

  • 我建议你比较查询计划而不是强制它使用索引。尽管从您的查询中并不明显,但可能有充分的理由不使用它。你也可以尝试重写一些东西。即用于生成IN 列表以限制具有四个特定属性的项目可能使用四个单独的EXISTS来更快的子表。

标签: sql-server join join-hints


【解决方案1】:

我相信你知道通常使用提示是一个坏主意,它应该只在非常特殊的情况下使用,但是......

create myview as
select mytable2.name
from mytable1 t1 WITH (INDEX(index_name1))
join myTable2 t2
WITH (INDEX(index_name2))
on t1.id = t2.id

【讨论】:

  • @Eitan 是的,您可以在创建视图时使用表格提示。但是,您不能使用查询提示。你需要这样做的原因对我来说非常非常晦涩。你之前的问题也得到了很好的答案。
  • 我在这篇文章中编辑了问题。请参阅更正(与提到的观点)。谢谢:)
  • 无论复杂程度如何,提示的语法都是一样的。只需在表别名后添加 WITH (INDEX(index_name)) 即可。但是我想重申一下,使用 HINT 并不是一个好主意,它应该只在 REAR REAR 情况下完成,我非常相信你可以创建适当的索引来解决你的问题。您不仅需要对 itemid 进行索引,还需要对参与 SELECT、WHERE、JOIN、GROUP BY、ORDER BY 子句的所有列进行覆盖索引
  • 您是否尝试过以下索引:CREATE NONCLUSTERED INDEX Ix_inventtable_itemid ON(itemid) INCLUDE (product,dataareaid); ?
  • 是的。上面有索引。
猜你喜欢
  • 2011-02-24
  • 2019-07-04
  • 2012-04-22
  • 2019-05-07
  • 2011-03-14
  • 2015-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多