ฉันพยายามเกลี้ยกล่อมให้มีประสิทธิภาพมากขึ้นจากการสืบค้นที่เข้าถึงตารางที่มีระเบียน ~ 250 ล้านรายการ จากการอ่านแผนปฏิบัติการจริง (ไม่ได้ประเมิน) ของฉันคอขวดแรกคือแบบสอบถามที่มีลักษณะดังนี้:
select
b.stuff,
a.added,
a.value
from
dbo.hugetable a
inner join
#smalltable b on a.fk = b.pk
where
a.added between @start and @end;
ดูเพิ่มเติมสำหรับคำจำกัดความของตารางและดัชนีที่เกี่ยวข้อง
แผนการดำเนินการบ่งชี้ว่ามีการใช้ลูปที่ซ้อนกันบน #smalltable และดัชนีการสแกนผ่าน hugetable กำลังดำเนินการ 480 ครั้ง (สำหรับแต่ละแถวใน #smalltable) สิ่งนี้ดูเหมือนจะย้อนกลับมาที่ฉันดังนั้นฉันจึงพยายามบังคับให้รวมการผสานเพื่อใช้แทน:
select
b.stuff,
a.added,
a.value
from
dbo.hugetable a with(index = ix_hugetable)
inner merge join
#smalltable b with(index(1)) on a.fk = b.pk
where
a.added between @start and @end;
ดัชนีในคำถาม (ดูด้านล่างสำหรับความหมายเต็ม) คอลัมน์ครอบคลุมFK (เข้าร่วมกริยา) เพิ่ม (ใช้ไปในข้อที่) และรหัส (ไม่มีประโยชน์) ในลำดับและรวมถึงความคุ้มค่า
เมื่อฉันทำเช่นนี้การค้นหาจะเริ่มจาก 2 1/2 นาทีไปจนถึง 9 ฉันหวังว่าคำแนะนำจะบังคับให้มีการเข้าร่วมที่มีประสิทธิภาพมากขึ้นซึ่งทำได้เพียงครั้งเดียวผ่านแต่ละตาราง แต่ไม่ชัดเจน
คำแนะนำใด ๆ ยินดีต้อนรับ ให้ข้อมูลเพิ่มเติมหากจำเป็น
อัปเดต (2011/06/02)
หลังจากจัดทำดัชนีใหม่บนโต๊ะฉันได้ทำการแสดงที่สำคัญ ๆ แล้วอย่างไรก็ตามฉันได้เจออุปสรรคใหม่เมื่อมันมาถึงการสรุปข้อมูลในตารางขนาดใหญ่ ผลลัพธ์คือการสรุปตามเดือนซึ่งปัจจุบันมีลักษณะดังนี้:
select
b.stuff,
datediff(month, 0, a.added),
count(a.value),
sum(case when a.value > 0 else 1 end) -- this triples the running time!
from
dbo.hugetable a
inner join
#smalltable b on a.fk = b.pk
group by
b.stuff,
datediff(month, 0, a.added);
ในปัจจุบันhugetableมีดัชนีคลัสเตอร์pk_hugetable (added, fk)
(คีย์หลัก) ix_hugetable (fk, added)
และดัชนีที่ไม่ใช่คลัสเตอร์ไปทางอื่น
หากไม่มีคอลัมน์ที่ 4 ด้านบนเครื่องมือเพิ่มประสิทธิภาพจะใช้การวนซ้ำแบบซ้อนกันเหมือนเดิมโดยใช้ #smalltable เป็นอินพุตด้านนอกและดัชนีที่ไม่ใช่คลัสเตอร์จะค้นหาเป็นวงใน (เรียกใช้งาน 480 ครั้ง) สิ่งที่เกี่ยวข้องกับฉันคือความแตกต่างระหว่างแถวที่ประเมิน (12,958.4) และแถวที่แท้จริง (74,668,468) ต้นทุนสัมพัทธ์ของการค้นหาเหล่านี้คือ 45% เวลาทำงานไม่เกินหนึ่งนาที
ด้วยคอลัมน์ที่ 4 เวลาในการรันจะเพิ่มขึ้นเป็น 4 นาที มันค้นหาดัชนีคลัสเตอร์ในครั้งนี้ (2 การประมวลผล) สำหรับค่าใช้จ่ายสัมพัทธ์เดียวกัน (45%) รวมผ่านการจับคู่แฮช (30%) จากนั้นทำการแฮชเข้าร่วมใน #smalltable (0%)
ฉันไม่แน่ใจว่าจะทำอะไรต่อไป ความกังวลของฉันคือไม่รับประกันการค้นหาช่วงวันที่หรือเข้าร่วมกริยาหรือแม้แต่สิ่งที่น่าจะลดชุดผลลัพธ์อย่างมาก ช่วงวันที่ในกรณีส่วนใหญ่จะตัดเพียง 10-15% ของเรคคอร์ดและการรวมภายในบนfkอาจกรองออกประมาณ 20-30%
ตามที่ขอโดย Will A ผลลัพธ์ของsp_spaceused
:
name | rows | reserved | data | index_size | unused
hugetable | 261774373 | 93552920 KB | 18373816 KB | 75167432 KB | 11672 KB
#smalltableถูกกำหนดเป็น:
create table #endpoints (
pk uniqueidentifier primary key clustered,
stuff varchar(6) null
);
ในขณะที่dbo.hugetableถูกกำหนดเป็น:
create table dbo.hugetable (
id uniqueidentifier not null,
fk uniqueidentifier not null,
added datetime not null,
value decimal(13, 3) not null,
constraint pk_hugetable primary key clustered (
fk asc,
added asc,
id asc
)
with (
pad_index = off, statistics_norecompute = off,
ignore_dup_key = off, allow_row_locks = on,
allow_page_locks = on
)
on [primary]
)
on [primary];
ด้วยการกำหนดดัชนีต่อไปนี้:
create nonclustered index ix_hugetable on dbo.hugetable (
fk asc, added asc, id asc
) include(value) with (
pad_index = off, statistics_norecompute = off,
sort_in_tempdb = off, ignore_dup_key = off,
drop_existing = off, online = off,
allow_row_locks = on, allow_page_locks = on
)
on [primary];
รหัสข้อมูลซ้ำซ้อน, สิ่งประดิษฐ์จาก DBA ก่อนหน้านี้ที่ยืนยันว่าทุกตารางทุกคนควรมี GUID ไม่มีข้อยกเว้น