เมื่อคุณมีแบบสอบถามหรือขั้นตอนการจัดเก็บที่ต้องการการปรับแต่งประสิทธิภาพสิ่งแรกที่คุณลองทำคืออะไร?
เมื่อคุณมีแบบสอบถามหรือขั้นตอนการจัดเก็บที่ต้องการการปรับแต่งประสิทธิภาพสิ่งแรกที่คุณลองทำคืออะไร?
คำตอบ:
นี่คือรายการสิ่งที่มีประโยชน์ที่ฉันมักจะมอบให้กับคนที่ถามฉันเกี่ยวกับการเพิ่มประสิทธิภาพ
เราใช้ Sybase เป็นหลัก แต่คำแนะนำส่วนใหญ่จะนำไปใช้ทั่วกระดาน
ตัวอย่างเช่น SQL Server มาพร้อมกับโฮสต์ของการตรวจสอบประสิทธิภาพ / การปรับแต่งบิต แต่ถ้าคุณไม่มีอะไรเช่นนั้น (และอาจถึงแม้ว่าคุณจะทำ) ฉันจะพิจารณาสิ่งต่อไปนี้ ...
99% ของปัญหาฉันได้เห็นจะเกิดจากการวางตารางมากเกินไปในการเข้าร่วม การแก้ไขสำหรับสิ่งนี้คือทำการรวมครึ่งหนึ่ง (กับบางตาราง) และแคชผลลัพธ์ในตารางชั่วคราว จากนั้นทำส่วนที่เหลือของแบบสอบถามเข้าร่วมในตารางชั่วคราวนั้น
#temp
ตารางอาจทำงานได้ดีกว่า@table
ตัวแปรที่มีปริมาณมาก (หลายพันแถว)นอกเรื่องเล็กน้อย แต่ถ้าคุณสามารถควบคุมปัญหาเหล่านี้ได้ ...
ระดับสูงและผลกระทบสูง
CREATE INDEX
ตรวจสอบให้แน่ใจว่ามีดัชนีสำหรับคุณWHERE
และJOIN
ข้อ ซึ่งจะช่วยเพิ่มความเร็วในการเข้าถึงข้อมูลอย่างมาก
หากสภาพแวดล้อมของคุณเป็นดาต้ามาร์ทหรือคลังสินค้าดัชนีควรมีอยู่มากมายสำหรับแบบสอบถามที่เป็นไปได้เกือบทั้งหมด
ในสภาพแวดล้อมการทำธุรกรรมจำนวนดัชนีควรต่ำกว่าและคำจำกัดความของดัชนีเหล่านี้มีกลยุทธ์มากขึ้นเพื่อให้การบำรุงรักษาดัชนีไม่ลากทรัพยากรลง (การบำรุงรักษาดัชนีคือเมื่อต้องเปลี่ยนใบของดัชนีเพื่อสะท้อนการเปลี่ยนแปลงในตารางพื้นฐานเช่นเดียวกับINSERT, UPDATE,
และDELETE
การดำเนินงาน)
นอกจากนี้โปรดคำนึงถึงลำดับของฟิลด์ในดัชนีด้วยยิ่งฟิลด์ที่เลือกมากขึ้น (จำนวนสมาชิกที่สูงกว่า) ก็จะยิ่งปรากฏในดัชนีก่อนหน้านี้ ตัวอย่างเช่นสมมติว่าคุณกำลังค้นหารถยนต์มือสอง:
SELECT i.make, i.model, i.price
FROM dbo.inventory i
WHERE i.color = 'red'
AND i.price BETWEEN 15000 AND 18000
ราคาโดยทั่วไปมีความสำคัญสูงกว่า อาจมีสีให้เลือกเพียงไม่กี่สี แต่อาจมีราคาที่แตกต่างกันหลายพันราคา
จากตัวเลือกดัชนีเหล่านี้idx01
ให้เส้นทางที่เร็วกว่าเพื่อตอบสนองแบบสอบถาม:
CREATE INDEX idx01 ON dbo.inventory (price, color)
CREATE INDEX idx02 ON dbo.inventory (color, price)
เนื่องจากรถยนต์จำนวนน้อยกว่าจะตอบสนองราคาได้มากกว่าการเลือกสีทำให้เครื่องมือสืบค้นข้อมูลในการวิเคราะห์น้อยกว่ามาก
ฉันเป็นที่ทราบกันดีว่ามีดัชนีที่คล้ายกันสองดัชนีที่แตกต่างกันเฉพาะในฟิลด์เพื่อเร่งความเร็วในการสืบค้น (ชื่อนามสกุล) ในหนึ่งและ (นามสกุล, ชื่อ) ในอีกดัชนี
เคล็ดลับที่เพิ่งเรียนรู้คือ SQL Server สามารถอัปเดตตัวแปรภายในและฟิลด์ในคำสั่งอัพเดต
UPDATE table
SET @variable = column = @variable + otherColumn
หรือรุ่นที่อ่านได้มากขึ้น:
UPDATE table
SET
@variable = @variable + otherColumn,
column = @variable
ฉันใช้สิ่งนี้เพื่อแทนที่เคอร์เซอร์ / การรวมที่ซับซ้อนเมื่อใช้การคำนวณแบบวนซ้ำและยังได้รับประสิทธิภาพมากมาย
นี่คือรายละเอียดและตัวอย่างโค้ดที่ปรับปรุงประสิทธิภาพได้อย่างยอดเยี่ยม: http://geekswithblogs.net/Rhames/archive/2008/10/28/calculating-running-totals-in-sql-server-2005---the-optimal aspx
สมมติว่า MySQL ที่นี่ใช้ EXPLAIN เพื่อค้นหาว่าเกิดอะไรขึ้นกับแบบสอบถามตรวจสอบให้แน่ใจว่าดัชนีถูกใช้อย่างมีประสิทธิภาพที่สุดเท่าที่จะเป็นไปได้และพยายามกำจัดประเภทไฟล์ High Performance MySQL: การเพิ่มประสิทธิภาพการสำรองข้อมูล, การจำลอง, และอื่น ๆเป็นหนังสือที่ดีในหัวข้อนี้เป็นบล็อก MySQL ผลการดำเนินงาน
@Terrapin มีความแตกต่างอื่น ๆ อีกเล็กน้อยระหว่าง isnull และ coalesce ที่ควรค่าแก่การกล่าวถึง (นอกเหนือจากการปฏิบัติตามข้อกำหนดของ ANSI ซึ่งเป็นเรื่องใหญ่สำหรับฉัน)
บางครั้งใน SQL Server ถ้าคุณใช้ OR ในส่วนคำสั่งที่มันจะแจ็คด้วยประสิทธิภาพจริงๆ แทนที่จะใช้ OR เพียงเลือกสองรายการแล้วรวมเข้าด้วยกัน คุณจะได้ผลลัพธ์เดียวกันที่ความเร็ว 1,000 เท่า
ดูที่คำสั่ง - ตรวจสอบการใช้ดัชนี / ตรวจสอบว่าไม่มีการทำอะไรโง่ ๆ
where SomeComplicatedFunctionOf(table.Column) = @param --silly
โดยทั่วไปฉันจะเริ่มต้นด้วยการรวม - ฉันจะเคาะแต่ละคนออกจากการสืบค้นทีละรายการและเรียกใช้การสืบค้นใหม่อีกครั้งเพื่อรับแนวคิดว่ามีการเข้าร่วมโดยเฉพาะที่ฉันมีปัญหาหรือไม่
ในตารางชั่วคราวทั้งหมดของฉันฉันต้องการเพิ่มข้อ จำกัด เฉพาะ (ตามความเหมาะสม) เพื่อสร้างดัชนีและคีย์หลัก (เกือบตลอดเวลา)
declare @temp table(
RowID int not null identity(1,1) primary key,
SomeUniqueColumn varchar(25) not null,
SomeNotUniqueColumn varchar(50) null,
unique(SomeUniqueColumn)
)
ฉันได้สร้างนิสัยที่จะใช้ตัวแปรการผูกเสมอ เป็นไปได้ว่าตัวแปรการผูกจะไม่ช่วยหาก RDBMS ไม่แคชคำสั่ง SQL แต่ถ้าคุณไม่ใช้ตัวแปรการผูก RDBMS จะไม่มีโอกาสนำแผนการดำเนินการสืบค้นกลับมาใช้ใหม่และคำสั่ง SQL ที่แยกวิเคราะห์ เงินฝากออมทรัพย์ได้อย่างมหาศาล: http://www.akadia.com/services/ora_bind_variables.html ฉันทำงานกับ Oracle เป็นส่วนใหญ่ แต่ Microsoft SQL Server ทำงานในลักษณะเดียวกัน
จากประสบการณ์ของฉันหากคุณไม่รู้ว่าคุณกำลังใช้ตัวแปรการผูกหรือไม่คุณก็อาจจะไม่ หากภาษาแอปพลิเคชันของคุณไม่รองรับให้หาภาษาที่รองรับ บางครั้งคุณสามารถแก้ไขแบบสอบถาม A ได้โดยใช้ตัวแปรการผูกสำหรับคิวรี B
หลังจากนั้นฉันคุยกับ DBA ของเราเพื่อค้นหาว่าอะไรทำให้ RDBMS เจ็บปวดมากที่สุด โปรดทราบว่าคุณไม่ควรถามว่า "เหตุใดข้อความค้นหานี้จึงช้า" นั่นเหมือนกับการขอให้แพทย์นำไส้ติ่งออก แน่ใจว่าคำถามของคุณอาจมีปัญหา แต่ก็เป็นไปได้ว่ามีข้อผิดพลาดเกิดขึ้น ในฐานะนักพัฒนาเรามักจะคิดในแง่ของบรรทัดของโค้ด ถ้าเส้นช้าให้แก้ไขเส้นนั้น แต่ RDBMS เป็นระบบที่ซับซ้อนมากและการสืบค้นที่ช้าของคุณอาจเป็นอาการของปัญหาที่ใหญ่กว่ามาก
เคล็ดลับการปรับแต่ง SQL มากเกินไปเป็นไอดอลของลัทธิขนส่งสินค้า โดยส่วนใหญ่ปัญหาจะไม่เกี่ยวข้องหรือเกี่ยวข้องกับไวยากรณ์ที่คุณใช้น้อยที่สุดดังนั้นโดยปกติแล้วคุณควรใช้ไวยากรณ์ที่สะอาดที่สุดเท่าที่จะทำได้ จากนั้นคุณสามารถเริ่มค้นหาวิธีปรับแต่งฐานข้อมูล (ไม่ใช่แบบสอบถาม) ปรับแต่งไวยากรณ์เมื่อล้มเหลวเท่านั้น
เช่นเดียวกับการปรับแต่งประสิทธิภาพใด ๆ ให้รวบรวมสถิติที่มีความหมายเสมอ อย่าใช้เวลาวอลล์เปเปอร์เว้นแต่จะเป็นประสบการณ์ของผู้ใช้ที่คุณกำลังปรับแต่ง ให้ดูสิ่งต่างๆเช่นเวลาของ CPU แถวที่ดึงข้อมูลและบล็อกที่อ่านออกจากดิสก์ บ่อยครั้งที่ผู้คนมองหาสิ่งที่ไม่ถูกต้อง
ขั้นตอนแรก: ดูแผนการดำเนินการสืบค้น!
TableScan ->
NestedLoop ที่ไม่ดี-> คำเตือน Meh
TableScan ที่อยู่เบื้องหลัง NestedLoop -> DOOM!
ตั้งค่าสถิติ IO ใน
เวลาที่ตั้งค่าสถิติ
การเรียกใช้แบบสอบถามโดยใช้ C (NoLock) เป็นการดำเนินการมาตรฐานในสถานที่ของฉัน ใครก็ตามที่พบว่ามีการสืบค้นบนตารางหลายสิบกิกะไบต์โดยที่ไม่ถูกนำออกมาและถูกยิง
แปลงคำค้นหา NOT IN เป็น LEFT OUTER JOINS ถ้าเป็นไปได้ ตัวอย่างเช่นหากคุณต้องการค้นหาแถวทั้งหมดใน Table1 ที่ไม่มีการใช้งานโดย Foreign Key ใน Table2 คุณสามารถทำได้:
SELECT *
FROM Table1
WHERE Table1.ID NOT IN (
SELECT Table1ID
FROM Table2)
แต่คุณจะได้รับประสิทธิภาพที่ดีขึ้นมากด้วยสิ่งนี้:
SELECT Table1.*
FROM Table1
LEFT OUTER JOIN Table2 ON Table1.ID = Table2.Table1ID
WHERE Table2.ID is null
@ DavidM
สมมติว่า MySQL ที่นี่ใช้ EXPLAIN เพื่อค้นหาว่าเกิดอะไรขึ้นกับแบบสอบถามตรวจสอบให้แน่ใจว่าดัชนีถูกใช้อย่างมีประสิทธิภาพที่สุด ...
ใน SQL Server แผนการดำเนินการทำให้คุณได้รับสิ่งเดียวกัน - จะบอกคุณว่าดัชนีใดที่ถูกตีเป็นต้น
จัดทำดัชนีตารางตาม clm (s) ที่คุณกรองด้วย
ไม่จำเป็นต้องเป็นเคล็ดลับประสิทธิภาพของ SQL ต่อ se แต่เกี่ยวข้องกันแน่นอน:
ความคิดที่ดีคือการใช้ memcached หากเป็นไปได้เนื่องจากจะเร็วกว่ามากเพียงแค่ดึงข้อมูลที่คอมไพล์ไว้ล่วงหน้าโดยตรงจากหน่วยความจำแทนที่จะดึงข้อมูลจากฐานข้อมูล นอกจากนี้ยังมีรสชาติของ MySQL ที่มี memcached ในตัว (บุคคลที่สาม)
ตรวจสอบให้แน่ใจว่าความยาวดัชนีของคุณมีขนาดเล็กที่สุด สิ่งนี้ช่วยให้ DB สามารถอ่านคีย์ได้มากขึ้นในแต่ละครั้งจากระบบไฟล์ดังนั้นการรวมของคุณจะเร็วขึ้น ฉันคิดว่าสิ่งนี้ใช้ได้กับ DB ทั้งหมด แต่ฉันรู้ว่าเป็นคำแนะนำเฉพาะสำหรับ MySQL
ฉันมองหา:
SET NOCOUNT ON
@@ROWCOUNT
โดยปกติบรรทัดแรกภายในวิธีการจัดเก็บของฉันเว้นแต่ที่จริงผมจำเป็นต้องใช้
ใน SQL Server ให้ใช้คำสั่ง nolock ช่วยให้คำสั่ง select เสร็จสมบูรณ์โดยไม่ต้องรอ - โดยปกติแล้วธุรกรรมอื่น ๆ จะเสร็จ
SELECT * FROM Orders (nolock) where UserName = 'momma'
ลบการเรียกฟังก์ชันใน Sprocs ซึ่งแถวจำนวนมากจะเรียกใช้ฟังก์ชัน
เพื่อนร่วมงานของฉันใช้การเรียกฟังก์ชัน (รับ lastlogindate จาก userid เป็นตัวอย่าง) เพื่อส่งคืนชุดระเบียนที่กว้างมาก
ได้รับมอบหมายให้เพิ่มประสิทธิภาพฉันแทนที่การเรียกฟังก์ชันใน sproc ด้วยรหัสของฟังก์ชัน: ฉันมีเวลาในการทำงานของ sprocs ลดลงจาก> 20 วินาทีเป็น <1
ฉันชอบที่จะใช้
isnull(SomeColThatMayBeNull, '')
เกิน
coalesce(SomeColThatMayBeNull, '')
เมื่อฉันไม่ต้องการการสนับสนุนหลายอาร์กิวเมนต์ที่รวมกันให้คุณ
http://blog.falafel.com/2006/04/05/SQLServerArcanaISNULLVsCOALESCE.aspx
อย่านำหน้าชื่อกระบวนงานที่เก็บไว้ด้วย "sp_" เนื่องจากโพรซีเดอร์ของระบบทั้งหมดขึ้นต้นด้วย "sp_" และ SQL Server จะต้องค้นหายากขึ้นเพื่อค้นหาโพรซีเดอร์ของคุณเมื่อถูกเรียก
set transaction isolation level read uncommitted
ป้องกันการล็อกที่ตายโดยที่ความสมบูรณ์ของธุรกรรมไม่จำเป็นอย่างยิ่ง (ซึ่งโดยปกติจะเป็นจริง)
ฉันมักจะไปที่ SQL Profiler (หากเป็นโพรซีเดอร์ที่จัดเก็บที่มีระดับการซ้อนกันจำนวนมาก) หรือตัววางแผนการดำเนินการสืบค้น (หากเป็นคำสั่ง SQL สองสามคำที่ไม่มีการซ้อนกัน) ก่อน 90% ของเวลาที่คุณสามารถพบปัญหาได้ทันทีด้วยหนึ่งในสองเครื่องมือนี้