แบบสอบถาม SQL Server ช้าเมื่อแบ่งหน้า


14

ฉันเห็นพฤติกรรมแปลก ๆ ด้วยแบบสอบถาม T-SQL ต่อไปนี้ใน SQL Server 2012:

SELECT Id 
FROM dbo.Person 
WHERE CONTAINS(Name, '"John" AND "Smith"')
ORDER BY Name

การดำเนินการค้นหานี้เพียงอย่างเดียวทำให้ฉันมีผลลัพธ์ประมาณ 1,300 รายการในเวลาน้อยกว่าสองวินาที (มีดัชนี fulltext เปิดอยู่Name)

อย่างไรก็ตามเมื่อฉันเปลี่ยนแบบสอบถามเป็น:

SELECT Id 
FROM dbo.Person 
WHERE CONTAINS(Name, '"John" AND "Smith"')
ORDER BY Name
OFFSET 0 rows
FETCH NEXT 10 ROWS ONLY

ใช้เวลามากกว่า 20 วินาทีในการให้ผลลัพธ์ 10 รายการ

แบบสอบถามต่อไปนี้ยิ่งแย่ลง:

SELECT Id 
FROM ( 
    SELECT ROW_NUMBER() OVER (ORDER BY Name) AS RowNum, Id 
    FROM dbo.Person
    WHERE CONTAINS(Name, '"John" AND "Smith"') ) AS RowConstrainedResult 
WHERE RowNum >= 0 AND RowNum < 11 
ORDER BY RowNum

ใช้เวลามากกว่า 1.5 นาทีจึงจะเสร็จสมบูรณ์!

ความคิดใด ๆ

แผนช้า

ช้า

แผนรวดเร็ว

รวดเร็ว


จะเกิดอะไรขึ้นถ้าคุณเปลี่ยนแบบสอบถามที่สองของคุณไปSELECT TOP 10 * .... ORDER BY Name?
Lamak

ดัชนี IX_PersonSearch ... สร้างคอลัมน์ใด คุณได้รับการค้นหาคีย์เนื่องจากคุณเลือก * จากตารางและดัชนีที่ใช้ไม่มีคอลัมน์เอาต์พุตทั้งหมด ฉันคิดว่าคุณควรเลือกเฉพาะคอลัมน์ที่คุณต้องการจากนั้นรวมไว้ในดัชนีที่ไม่รวมกลุ่มเป็นคอลัมน์ที่รวมไม่ใช่คอลัมน์ดัชนี
Marcel N.

คุณช่วยโพสต์ดัชนีของคุณบนโต๊ะ (สร้างสคริปต์) ได้ไหม?

3
ID จะรวมอยู่ในดัชนีที่ไม่ใช่คลัสเตอร์ทุกครั้ง นี่คือวิธีที่ SQL Server สามารถค้นหาคีย์ (ตาม ID)
usr

1
สิ่งที่ฉันลืมพูดถึง: เมื่อฉันทำแบบสอบถามเดียวกันกับ LIKE แทนที่จะมี CONTAINS ก็รวดเร็วเช่นกัน (เลขหน้าหรือไม่)

คำตอบ:


7

ในขณะที่คุณต้องการTOP 10เรียงตามชื่อก็คิดว่ามันจะเร็วกว่าที่จะจัดทำดัชนีตามnameลำดับและดูว่าแต่ละแถวตรงกับCONTAINS(Name, '"John" AND "Smith"') )คำกริยาหรือไม่

สันนิษฐานว่าอาจต้องใช้แถวเพิ่มอีกหลายแถวเพื่อค้นหา 10 รายการที่ต้องการจากนั้นจึงคาดว่าปัญหานี้จะเกิดขึ้นจากจำนวนการค้นหาที่สำคัญ

แฮ็คอย่างรวดเร็วเพื่อหยุดมันโดยใช้แผนนี้จะเปลี่ยน ORDER BYถึงORDER BY Name + ''แม้ว่าการใช้CONTAINSTABLEร่วมกับFORCE ORDERควรทำงาน


3

ดูเหมือนว่าการเลือกสรรแบบผิด ๆ ไม่แน่ใจว่าสามารถทำอะไรได้บ้างเนื่องจาก "ไดรเวอร์" ของข้อความค้นหาคือการค้นหาแบบเต็มซึ่งคุณไม่สามารถเพิ่มด้วยสถิติได้

ลองเขียนเพรดิเคตใหม่where containsเป็นinner join containstable(เพรดิเคต CONTAINSTABLE ) และใช้คำแนะนำการเข้าร่วมเพื่อบังคับใช้รูปร่างของแผน

นั่นไม่ใช่วิธีที่สมบูรณ์แบบเพราะมันมีปัญหาการบำรุงรักษา แต่ฉันไม่สามารถมองเห็นวิธีอื่นได้


ขอบคุณสำหรับคำตอบของคุณฉันลองแล้ว แม้ว่าผลลัพธ์เดียวกัน: เมื่อไม่ได้ใช้การแบ่งหน้าแบบสอบถามจะเร็วมาก เมื่อ Paginating มันก็จะช้าอีกครั้งจริงๆ: /

คุณสามารถโพสต์แผนเป็นรูปภาพและคิวรีของคุณได้ไหม ฉันเดาว่าเรายังไม่ประสบความสำเร็จในการสร้างรูปร่างที่ต้องการ
usr

3

ฉันจัดการเพื่อแก้ปัญหา:

ดังที่ฉันพูดในคำถามมีสิ่งบ่งชี้ในคอลัมน์ + สถิติทั้งหมดสำหรับแต่ละคอลัมน์ (เนื่องจากข้อความค้นหา LIKE แบบดั้งเดิม) ฉันลบสิ่งที่แนบมาและสถิติทั้งหมดออกเพิ่มการค้นหาแบบเต็มและข้อความทำให้การค้นหากลายเป็นเรื่องรวดเร็วมาก

ดูเหมือนว่าสิ่งที่เกิดขึ้นจะนำไปสู่แผนการปฏิบัติที่แตกต่าง

ขอบคุณมากสำหรับความช่วยเหลือของคุณ!


1
การลบดัชนีทั้งหมดเป็นวิธีหนึ่งในการป้องกันไม่ให้ใช้ฉันเดา!
Martin Smith
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.