ฉันจะลบแผนการดำเนินการที่ไม่ดีออกจากฐานข้อมูล Azure SQL ได้อย่างไร


12

DBCC FREEPROCCACHEไม่ทำงานใน Azure SQL DB ฉันจะบังคับให้มีแผนอื่นเพื่อปลดปล่อยตัวเองออกจากแคชในลักษณะที่จะไม่ทำให้ระบบการผลิตเสียหาย (เช่นฉันไม่สามารถไปเปลี่ยนตารางที่จำใจได้) นี่เป็นเฉพาะสำหรับ SQL ที่สร้างโดย Entity Framework ดังนั้นจึงไม่ใช่ procs ที่จัดเก็บด้วยตนเองซึ่งมันคือไดนามิก SQL ที่มีประสิทธิภาพ

(แหล่งที่มาคือดัชนีที่ไม่ดี -> สถิติที่ไม่ดี ฯลฯ นั่นคือทั้งหมดที่ได้รับการแก้ไข แต่แผนไม่ดีจะไม่หายไป)

อัปเดต: ฉันเลือกโซลูชันของ @ mrdenny เมื่อเขาไปถึงที่นั่นก่อน อย่างไรก็ตามฉันใช้สคริปต์ของ @Aaron Bertrand สำเร็จในการทำงาน ขอบคุณทุกคนสำหรับความช่วยเหลือ !!


คุณสามารถทำ sp_recompile ใน Azure ได้หรือไม่?
mrdenny

ใช่. ฉันจะเรียกใช้มันอย่างไร เราไม่มี procs ที่เก็บไว้ นี่คือ SQL sp_executesqlแบบไดนามิกวิ่งเข้าไปในห้อง
Jaxidian

2
คุณสามารถเรียกใช้งานบนตารางได้ด้วยตนเองและควรล้างข้อมูลแผนการที่ใช้ตารางนั้น (ถ้างานนี้ฉันจะทำให้มันเป็นคำตอบ.)
mrdenny

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

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

คำตอบ:


12

ขณะนี้ Azure SQL สนับสนุนสิ่งนี้โดยตรง

Azure SQL Database สนับสนุนการล้างแคช proc ของฐานข้อมูลผู้ใช้ปัจจุบันโดยตรงโดยไม่แฮ็คใด ๆ :

ALTER DATABASE SCOPED CONFIGURATION CLEAR PROCEDURE_CACHE;

ข้อมูลเพิ่มเติม

สคริปต์ต่อไปนี้ (โดยShannon Gowen ) สามารถใช้เพื่อดูกระบวนการทีละขั้นตอน:

-- run this script against a user database, not master
-- count number of plans currently in cache
select count(*) from sys.dm_exec_cached_plans;

-- Executing this statement will clear the procedure cache in the current database, which means that all queries will have to recompile.
ALTER DATABASE SCOPED CONFIGURATION CLEAR PROCEDURE_CACHE;

-- count number of plans in cache now, after they were cleared from cache
select count(*) from sys.dm_exec_cached_plans;

-- list available plans
select * from sys.dm_exec_cached_plans;

ฉันยังไม่ได้ลองเลย แต่ถ้ามันใช้งานได้จริงนี่อาจเป็นคำตอบที่ "ดีที่สุด" ณ ต้นปี 2560 ขอบคุณสำหรับสิ่งนี้ - ฉันไม่มีเงื่อนงำที่นี่! :-)
Jaxidian

ฉันได้ลองแล้ว (บนฐานข้อมูลระดับพรีเมียม) และใช้งานได้
Remi Lemarchand

ฉันตั้งค่าสถานะนี้เป็น "คำตอบที่ยอมรับแล้ว" แล้ว แต่ยังไม่ได้ทำการทดสอบด้วยตนเอง ฉันกำลังพูดถึงความคิดเห็นของทอดด์และ Remi โดยตรง ขอบคุณทุกคน!
Jaxidian

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

ดูเหมือนจะใช้งานไม่ได้สำหรับฉัน - เพียงแค่เรียกใช้งาน แต่รายการยังคงเต็ม - ฉันใช้ SQL Azure - เกิดอะไรขึ้น
เดิร์คโบเออร์

12

ไม่มีวิธีที่ชัดเจนในการทำเช่นนี้ในวันนี้ แต่นั่นไม่ใช่สถานการณ์ถาวร (คำสั่ง DBCC ยังไม่ได้รับการสนับสนุน แต่อ่านได้จากQuery Store ) แม้ว่าจะยอมรับการเปลี่ยนสคีมา แต่ก็อาจไม่ใช่สิ่งที่คุณต้องการเพราะมันจะทำให้แผนการทั้งหมดที่เกี่ยวข้องกับวัตถุต้นแบบนั้นไม่ถูกต้อง

ไม่ได้มองหาเครดิตสำหรับสิ่งนี้ แต่การสร้าง SQL แบบไดนามิกเพื่อดำเนินการเดียวกันกับหลาย ๆ ตารางนั้นค่อนข้างง่าย:

DECLARE @sql NVARCHAR(MAX) = N'';

SELECT @sql += N'ALTER TABLE '
  + QUOTENAME(SCHEMA_NAME([schema_id])) 
  + '.' + QUOTENAME(name) + ' ADD fake_column INT NULL;
  ALTER TABLE ' 
  + QUOTENAME(SCHEMA_NAME([schema_id]))
  + '.' + QUOTENAME(name) + ' DROP COLUMN fake_column;'
FROM sys.tables
--WHERE name IN, LIKE, etc.

PRINT @sql;

-- if the command > 8K, you can see the second chunk e.g.

PRINT SUBSTRING(@sql, 8001, 8000);

--EXEC sys.sp_executesql @sql;

(ฉันเขียนเคล็ดลับเกี่ยวกับปัญหา "ความยาวของไดนามิก SQL" นี้ ... )


ในกรณีของฉันการลบพวกเขาทั้งหมดออกจะดีกว่าที่จะทิ้งคนเลวเอาไว้ ขอบคุณสำหรับหัวขึ้น. ฉันรู้ว่าคุณไม่สามารถบอกคุณสมบัติได้ แต่คุณสามารถบอกฉันได้เมื่อคุณอาจไม่ถูก จำกัด เกี่ยวกับการพูดคุยเกี่ยวกับสิ่งที่คุณไม่สามารถพูดคุยได้อีกต่อไป? ;-)
Jaxidian

นั่นก็จัดว่าขอโทษ :-)
Aaron Bertrand

ไม่แน่ใจว่าลิงค์นั้นหมายถึงอะไร สิ่งที่ผมหมายถึงคือการที่คุณnvarchar(max)ตัวแปรยอดวงเงินหลังจากที่ 4000 ตัวอักษร, ตัวอักษร 8000 varchar(max)ถ้าผมเปลี่ยนไป เรียกใช้สคริปต์ที่แน่นอน เรามีตารางประมาณ 450 ตารางดังนั้นเราจึงตีอย่างง่ายดาย (~ 30/60 ตารางใน) varchar(max)ไวยากรณ์ที่ถูกต้องก็แค่เหมือนกันvarchar(8000)และเป็นเหมือนnvarchar(max) nvarchar(4000)
Jaxidian

3
ใช่เมื่อคุณPRINTสั่งมันจะแสดงเพียง 8000 ไบต์ นั่นเป็นข้อ จำกัด ของPRINTคำสั่งไม่ใช่ Azure หากคุณเรียกใช้คำสั่งมันจะทำงานแม้ว่าคุณจะไม่สามารถตรวจสอบทุกสิ่งได้
Aaron Bertrand

... doh ขอโทษฉันคิดว่าคุณพูดถูก! ขอบคุณสำหรับการแก้ไขฉัน! นั่นคือสิ่งที่เกิดขึ้นเมื่อภรรยาของคุณคาดหวังว่าคุณจะจากไปเมื่อ 25 นาทีก่อน ... ;-) สคริปต์นี้ทำงานได้อย่างสมบูรณ์แบบสำหรับฉัน!
Jaxidian

6

เพิ่มคอลัมน์ nullable ลงในตารางจากนั้นปล่อยคอลัมน์ นั่นจะบังคับให้ SQL ล้างแคชสำหรับวัตถุนั้น

สำหรับการทำตารางทั้งหมดเคอร์เซอร์ควรใช้เล่ห์เหลี่ยม เพียงใช้ชื่อคอลัมน์ที่จะไม่มีอยู่ในตารางใด ๆ เช่น 'zzzzzz_go_away' หรืออะไรบางอย่าง


4

ขณะนี้ฐานข้อมูล Azure SQL ไม่รองรับDBCC FREEPROCCACHEดังนั้นคุณไม่สามารถลบแผนการดำเนินการออกจากแคชได้ด้วยตนเอง อย่างไรก็ตามหากคุณทำการเปลี่ยนแปลงตารางหรือมุมมองที่อ้างอิงโดยแบบสอบถาม ( ALTER TABLE/ ALTER VIEW) แผนจะถูกลบออกจากแคช ( ข้อมูลอ้างอิง )


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

1
คุณสามารถเพิ่มคอลัมน์ดัมมี่แล้วปล่อย นี่จะเป็นการลบแผนออกจากแคช โต๊ะใหญ่แค่ไหน?
Kin Shah

นั่นเป็นวิธีการแก้ปัญหาตามที่ @mrdenny แนะนำ ขอบคุณสำหรับความช่วยเหลือ !! :-)
Jaxidian

1
ขอบคุณ ... เพียงแค่ไม่กี่วินาทีสั้น ๆ ในเวลา .. ได้รับการตอบโพสต์อื่น ๆ บางอย่างเกี่ยวกับ stackexchange ...
Kin ชาห์

1

หากต้องการล้างแผนปฏิบัติการทั้งหมดให้ใช้สิ่งนี้:

    SET NOCOUNT ON

DECLARE @lcl_name VARCHAR(100)
DECLARE @addcolumnSql nVARCHAR(MAX)
DECLARE @dropcolumnSql nVARCHAR(MAX)

DECLARE cur_name CURSOR FOR
SELECT name
FROM sysobjects
WHERE type = 'U'
OPEN cur_name
FETCH NEXT FROM cur_name INTO @lcl_name
WHILE @@Fetch_status = 0
BEGIN
set @addcolumnSql = 'alter table [' + @lcl_name + '] add temp_col_to_clear_exec_plan bit'
EXEcute sp_executesql @addcolumnSql
print @addcolumnSql
set @dropcolumnSql = 'alter table [' + @lcl_name + '] drop column temp_col_to_clear_exec_plan'
EXEcute sp_executesql @dropcolumnSql
print @dropcolumnSql
--  EXEC (@lcl_name )
FETCH NEXT FROM cur_name INTO @lcl_name
END
CLOSE cur_name
DEALLOCATE cur_name
SET NOCOUNT OFF

หากคุณเปลี่ยนตารางหรือมุมมองที่อ้างอิงมันแผนการดำเนินการจะถูกล้าง

มากขึ้นอีกนิดอธิบายที่นี่http://christianarg.wordpress.com/2013/08/22/remove-execution-plans-from-the-procedure-cache-in-sql-azure/

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