การสแกนคงที่ใช้เวลา 0 วินาทีหรือ 2-3 นาที


9

แบบสอบถามเช่นเดียวกับด้านล่างที่รับประกันว่าจะไม่ส่งคืนแถวใด ๆ ใช้เวลาตั้งแต่ 0 ถึง 160 วินาทีในเซิร์ฟเวอร์ของเรา:

select col1, col2, col3
from tab1
where 0 = 1

สองสัปดาห์ที่ผ่านมาสิ่งนี้เกิดขึ้นหกครั้งในช่วงเวลา 48 ชั่วโมง เมื่อสัปดาห์ที่แล้วข้อความค้นหาเดียวกันใช้เวลาประมาณ 0 วินาที ฉันมีบันทึกของ SQL ของแอปพลิเคชันของเรา แต่ยังไม่พบผู้ต้องสงสัย นอกจากนี้ฉันคิดว่าคำถามอันดับสูงสุด 0 / โดยที่ 0 = 1 แบบสอบถามชนิดไม่เคยตีหน้าข้อมูลดังนั้นจึงควรต้านทานล็อคข้อมูลแถว / หน้า / ระดับตาราง? สกีมาไม่ได้ถูกแตะต้องโดย SQL (รู้) ใด ๆ

เนื่องจากปัญหาไม่สอดคล้องกันและเซิร์ฟเวอร์อยู่ภายใต้ภาระงานหนักมากฉันต้องการทำความเข้าใจทฤษฎีเบื้องหลังสิ่งที่เกิดขึ้นก่อนที่จะแนบ SQL profiler การสืบค้นอื่น ๆ จะทำงานโดยไม่มีปัญหาในระหว่างการล่าช้า ปัญหาที่ทราบในแอปพลิเคชั่นคือแบบสอบถาม SQL ที่สร้างขึ้นแบบไดนามิกจำนวนมากโดยมีข้อความค้นหาที่ไม่ซ้ำกันประมาณ 200k ข้อความค้นหาแบบรวม (บันทึก) 850k ภายในระยะเวลา 48 ชั่วโมงจะทำให้เกิดปัญหาเช่นนี้ได้หรือไม่

เซิร์ฟเวอร์กำลังเรียกใช้ SQL Server 2005 Standard Edition, RAM 96 GB, ดิสก์บน SAN และ 4 CPUs / 16 คอร์ ไฟล์ฐานข้อมูลและกลุ่มไฟล์นั้นได้รับการปรับปรุงให้ดีที่สุดและไม่น่าจะมีปัญหา (แต่เราแยกวิเคราะห์เรื่องนี้)

คำแนะนำใด ๆ ที่จะดูชื่นชมอย่างมาก

แก้ไข: สมบูรณ์แบบ! เล่นซ้ำแบบสอบถามเพื่อเพิ่มแผนการดำเนินการและใช้เวลา 1 นาที 35 วินาที นี่คือแผนการดำเนินการและภาพหน้าจอที่แสดงระยะเวลาการสืบค้น: แผนแบบสอบถาม

แก้ไข 2: รายละเอียดเวลาสถิติสำหรับการวิ่งครั้งที่สอง ดูเหมือนว่าจะช้าอย่างสม่ำเสมอในขณะนี้ดังนั้นเราจะแนบ profiler และ perfmon:

SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 97402 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

คุณช่วยรวมแผนปฏิบัติการไว้ด้วยได้ไหม? CTRL + M ในหน้าต่างแบบสอบถามก่อนดำเนินการ
Craig Efrein

2
มันอาจเป็นปัญหาการล็อคหรือไม่ คำสั่ง DML จากเซสชันอื่น ๆ บล็อกตัวเลือกบนตาราง (ซึ่งเป็นพฤติกรรมเริ่มต้นใน SQL Server 2005)
a_horse_with_no_name

ไม่มีคำสั่งใด ๆ - รู้จัก - DML ซึ่งเป็นสาเหตุเดียวที่ฉันนึกออก แต่เรายังคงตรวจสอบอยู่ แผนการดำเนินการถูกเพิ่มเข้าไปในคำถาม
EventHorizon

จากสิ่งที่ฉันได้อ่านนี่เป็นเพียงหนึ่งในแผนปฏิบัติการเล็กน้อยที่ MSSQL ใช้เพื่อหลีกเลี่ยงการอ่านฮีปและดัชนีเมื่อเครื่องมือเพิ่มประสิทธิภาพรู้ว่าไม่มีแถวที่จะส่งคืน
Craig Efrein

1
เห็นกรณีที่ดูเหมือนมากนี้ ดูเหมือนจะเป็นการเปิดใช้งานสถิติการอัปเดต (เปิดใช้งานสถิติการอัพเดทอัตโนมัติและแผนการบำรุงรักษาเสียหาย)
Joshua

คำตอบ:


18

ดูเหมือนว่าแม้จะมีส่วน... WHERE 0 = 1คำสั่งที่จะยังคงมีความต้องการISล็อคเจตนาที่ใช้ร่วมกัน ( ) บนโต๊ะ มาพิสูจน์กันเถอะ:

ฉันจะเริ่มต้นด้วยการสร้างตารางทดสอบ:

use TestDb1;
go

create table dbo.MyTestTable1
(
    Id int identity(1, 1) not null,
    SomeInt int not null
);
go

insert into dbo.MyTestTable1 (SomeInt)
values (10), (20), (30), (40), (50);
go

ตอนนี้ฉันมีตารางทดสอบของฉันในหนึ่งเซสชัน (หน้าต่างแบบสอบถาม) ฉันจะดำเนินการต่อไปนี้เพื่อวางXล็อคพิเศษ ( ) บนdbo.MyTestTable1:

use TestDb1;
go

begin tran;
    select
        Id, SomeInt
    from dbo.MyTestTable1 with (tablockx);
--commit tran;

ฉันสามารถตรวจสอบล็อคพิเศษโดยดูที่sys.dm_tran_locksDMV จากนั้นในเซสชั่นอื่น (หน้าต่างแบบสอบถามใหม่) ฉันจะทำสิ่งที่แบบสอบถามของคุณ:

use TestDb1;
go

select
    Id, SomeInt
from dbo.MyTestTable1
where 0 = 1;

ในแวบแรกฉันเห็นว่ามันยังไม่เสร็จ มองไปที่sys.dm_exec_requestsฉันเห็นว่าทำไมกรณีนี้:

select
    r.session_id,
    r.status,
    r.wait_type,
    r.wait_time,
    r.wait_resource,
    r.blocking_session_id
from sys.dm_exec_requests r
cross apply sys.dm_exec_sql_text(r.sql_handle) st
where st.text like '%where 0 = 1%'
and r.session_id <> @@spid;

ป้อนคำอธิบายรูปภาพที่นี่

ฉันเห็นได้ว่า... WHERE 0 = 1ข้อความค้นหาของฉันกำลังรอการISล็อคสำหรับวัตถุนี้ (object_id นั้นแปลว่าdbo.MyTestTable1)

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

ทั้งหมดที่เราทำได้คือเดาดังนั้นสิ่งที่คุณต้องทำเมื่อ "ใช้เวลานาน" คือดูว่าสิ่งที่คำขอนั้นทำนั้นใช้เวลานานขนาดไหน หากกำลังรออะไรอยู่ให้ดูว่ากำลังรออะไรอยู่


1

ระบบของคุณอาจรอคิวรีนั้นโดยขึ้นอยู่กับว่าแหลมคมและเธรดเรียกร้องข้อความค้นหาของคุณอย่างไร จำนวนผู้ปฏิบัติงานเริ่มต้น (เช่นจำนวนเธรดเซิร์ฟเวอร์ SQL พร้อมกัน) สำหรับการตั้งค่าของคุณควรประมาณ 700

ลองใช้ sys.dm_os_schedulers และ sys.dm_os_waiting_tasks เพื่อดูว่าเป็นปัญหาหรือไม่


คำแนะนำที่ดี แต่ปัญหาก็จบลงด้วยการล็อคโง่ ๆ
EventHorizon

ฉันไม่มั่นใจจริง ๆ เพราะมีคนงาน 700 คนมากมาย แต่ง่ายต่อการตรวจสอบ (และไม่รวมอยู่ด้วย)
Sascha Rambeaud
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.