ติดตั้ง:
create table dbo.T
(
ID int identity primary key,
XMLDoc xml not null
);
insert into dbo.T(XMLDoc)
select (
select N.Number
for xml path(''), type
)
from (
select top(10000) row_number() over(order by (select null)) as Number
from sys.columns as c1, sys.columns as c2
) as N;
ตัวอย่าง XML สำหรับแต่ละแถว:
<Number>314</Number>
งานสำหรับการค้นหาคือการนับจำนวนแถวในที่มีค่าที่กำหนดT
<Number>
มีสองวิธีที่ชัดเจนในการทำสิ่งนี้:
select count(*)
from dbo.T as T
where T.XMLDoc.value('/Number[1]', 'int') = 314;
select count(*)
from dbo.T as T
where T.XMLDoc.exist('/Number[. eq 314]') = 1;
ปรากฎว่าvalue()
และexists()
ต้องการนิยามพา ธ สองแบบที่แตกต่างกันเพื่อให้ดัชนี XML แบบเลือกทำงานได้
create selective xml index SIX_T on dbo.T(XMLDoc) for
(
pathSQL = '/Number' as sql int singleton,
pathXQUERY = '/Number' as xquery 'xs:double' singleton
);
sql
รุ่นสำหรับvalue()
และรุ่นสำหรับxquery
exist()
คุณอาจคิดว่าดัชนีแบบนี้จะให้แผนกับการค้นหาที่ดี แต่ดัชนี XML แบบเลือกจะถูกนำไปใช้เป็นตารางระบบที่มีคีย์หลักT
เป็นคีย์นำของคีย์คลัสเตอร์ของตารางระบบ เส้นทางที่ระบุเป็นคอลัมน์กระจัดกระจายในตารางนั้น หากคุณต้องการให้ดัชนีของค่าที่แท้จริงของเส้นทางที่กำหนดคุณจำเป็นต้องสร้างดัชนีเลือกรองหนึ่งสำหรับแต่ละการแสดงออกของเส้นทาง
create xml index SIX_T_pathSQL on dbo.T(XMLDoc)
using xml index SIX_T for (pathSQL);
create xml index SIX_T_pathXQUERY on dbo.T(XMLDoc)
using xml index SIX_T for (pathXQUERY);
แผนแบบสอบถามสำหรับการexist()
ค้นหาในดัชนี XML รองตามด้วยการค้นหาคีย์ในตารางระบบสำหรับดัชนี XML ที่เลือก (ไม่ทราบสาเหตุที่จำเป็น) และสุดท้ายจะทำการค้นหาT
เพื่อให้แน่ใจว่ามี แถวในนั้น ส่วนสุดท้ายเป็นสิ่งจำเป็นเพราะไม่มีข้อ จำกัด T
ที่สำคัญต่างประเทศระหว่างตารางระบบและ
แผนสำหรับvalue()
แบบสอบถามไม่ดีนัก มันจะทำการสแกนดัชนีแบบกลุ่มที่T
มีลูปซ้อนกันรวมกับการค้นหาในตารางภายในเพื่อรับค่าจากคอลัมน์กระจัดกระจายและในที่สุดก็กรองค่า
หากดัชนีแบบเลือกควรใช้หรือไม่ตัดสินใจก่อนการปรับให้เหมาะสม แต่ถ้าดัชนีแบบเลือกรองควรใช้หรือไม่เป็นการตัดสินใจตามต้นทุนโดยเครื่องมือเพิ่มประสิทธิภาพ
ทำไมดัชนีการคัดเลือกรองไม่ได้ใช้เมื่อที่ฟิลเตอร์ข้อบนvalue()
?
ปรับปรุง:
แบบสอบถามแตกต่างกันในเชิงความหมาย หากคุณเพิ่มแถวด้วยค่า
<Number>313</Number>
<Number>314</Number>`
exist()
รุ่นจะนับ 2 แถวและvalues()
แบบสอบถามจะนับ 1 แถว แต่ด้วยนิยามดัชนีตามที่ระบุไว้ที่นี่โดยใช้singleton
คำสั่ง SQL Server จะป้องกันคุณจากการเพิ่มแถวที่มี<Number>
องค์ประกอบหลายรายการ
อย่างไรก็ตามนั่นไม่อนุญาตให้เราใช้values()
ฟังก์ชั่นโดยไม่ระบุ[1]
เพื่อรับประกันคอมไพเลอร์ว่าเราจะได้รับค่าเดียวเท่านั้น นั่น[1]
คือเหตุผลที่เรามี Top N Sort ในvalue()
แผน
ดูเหมือนว่าฉันจะปิดคำตอบที่นี่ ...