เพิ่มเติม: SQL Server 2012 แสดงประสิทธิภาพที่ดีขึ้นในพื้นที่นี้ แต่ดูเหมือนจะไม่สามารถแก้ไขปัญหาเฉพาะที่ระบุไว้ด้านล่าง เห็นได้ชัดว่าสิ่งนี้ควรได้รับการแก้ไขในเวอร์ชันหลักถัดไปหลังจาก
SQL Server 2012!
แผนของคุณแสดงให้เห็นว่าเม็ดมีดเดี่ยวกำลังใช้ขั้นตอนที่กำหนดพารามิเตอร์ (อาจเป็นพารามิเตอร์อัตโนมัติ) ดังนั้นเวลาในการแยกวิเคราะห์ / รวบรวมควรน้อยที่สุด
ฉันคิดว่าฉันจะพิจารณาเรื่องนี้ให้มากขึ้นแม้ว่าจะตั้งค่าลูป ( สคริปต์ ) และลองปรับจำนวนVALUES
ประโยคและบันทึกเวลาในการคอมไพล์
จากนั้นฉันแบ่งเวลาคอมไพล์ด้วยจำนวนแถวเพื่อให้ได้เวลาคอมไพล์เฉลี่ยต่อข้อ ผลลัพธ์อยู่ด้านล่าง
จนถึง 250 VALUES
ข้อแสดงเวลาในการคอมไพล์ / จำนวนข้อมีแนวโน้มสูงขึ้นเล็กน้อย แต่ไม่มีอะไรน่าทึ่งเกินไป
แต่แล้วก็มีการเปลี่ยนแปลงอย่างกะทันหัน
ข้อมูลส่วนนั้นแสดงอยู่ด้านล่าง
+------+----------------+-------------+---------------+---------------+
| Rows | CachedPlanSize | CompileTime | CompileMemory | Duration/Rows |
+------+----------------+-------------+---------------+---------------+
| 245 | 528 | 41 | 2400 | 0.167346939 |
| 246 | 528 | 40 | 2416 | 0.162601626 |
| 247 | 528 | 38 | 2416 | 0.153846154 |
| 248 | 528 | 39 | 2432 | 0.157258065 |
| 249 | 528 | 39 | 2432 | 0.156626506 |
| 250 | 528 | 40 | 2448 | 0.16 |
| 251 | 400 | 273 | 3488 | 1.087649402 |
| 252 | 400 | 274 | 3496 | 1.087301587 |
| 253 | 400 | 282 | 3520 | 1.114624506 |
| 254 | 408 | 279 | 3544 | 1.098425197 |
| 255 | 408 | 290 | 3552 | 1.137254902 |
+------+----------------+-------------+---------------+---------------+
ขนาดแผนแคชที่เพิ่มขึ้นในเชิงเส้นก็ลดลงอย่างกะทันหัน แต่ CompileTime เพิ่มขึ้น 7 เท่าและ CompileMemory ก็เพิ่มขึ้น นี่คือจุดตัดระหว่างแผนเป็นหนึ่งพารามิเตอร์อัตโนมัติ (ที่มีพารามิเตอร์ 1,000 รายการ) ไปยังจุดที่ไม่ใช่พารามิเตอร์ หลังจากนั้นดูเหมือนว่าจะมีประสิทธิภาพน้อยลงเชิงเส้น (ในแง่ของจำนวนประโยคค่าที่ประมวลผลในเวลาที่กำหนด)
ไม่แน่ใจว่าทำไมถึงเป็นเช่นนี้ สันนิษฐานว่าเมื่อรวบรวมแผนสำหรับค่าตัวอักษรที่เฉพาะเจาะจงจะต้องดำเนินกิจกรรมบางอย่างที่ไม่ได้ปรับขนาดเชิงเส้น (เช่นการเรียงลำดับ)
ดูเหมือนว่าจะไม่มีผลกับขนาดของแผนแบบสอบถามที่แคชไว้เมื่อฉันลองใช้แบบสอบถามที่ประกอบด้วยแถวที่ซ้ำกันทั้งหมดและไม่มีผลต่อลำดับของผลลัพธ์ของตารางของค่าคงที่ (และในขณะที่คุณกำลังแทรกลงในเวลาฮีปที่ใช้ในการเรียงลำดับ จะไม่มีจุดหมายต่อไปแม้ว่าจะเป็นเช่นนั้นก็ตาม)
ยิ่งไปกว่านั้นหากมีการเพิ่มดัชนีคลัสเตอร์ลงในตารางแผนจะยังคงแสดงขั้นตอนการจัดเรียงที่ชัดเจนดังนั้นจึงดูเหมือนว่าจะไม่มีการเรียงลำดับในเวลาคอมไพล์เพื่อหลีกเลี่ยงการเรียงลำดับในขณะรัน
ฉันพยายามดูสิ่งนี้ในดีบักเกอร์ แต่ดูเหมือนว่าสัญลักษณ์สาธารณะสำหรับ SQL Server 2008 เวอร์ชันของฉันไม่พร้อมใช้งานดังนั้นฉันต้องดูสิ่งที่เทียบเท่าแทน UNION ALL
ใน SQL Server 2005 แทน
การติดตามสแต็กทั่วไปอยู่ด้านล่าง
sqlservr.exe!FastDBCSToUnicode() + 0xac bytes
sqlservr.exe!nls_sqlhilo() + 0x35 bytes
sqlservr.exe!CXVariant::CmpCompareStr() + 0x2b bytes
sqlservr.exe!CXVariantPerformCompare<167,167>::Compare() + 0x18 bytes
sqlservr.exe!CXVariant::CmpCompare() + 0x11f67d bytes
sqlservr.exe!CConstraintItvl::PcnstrItvlUnion() + 0xe2 bytes
sqlservr.exe!CConstraintProp::PcnstrUnion() + 0x35e bytes
sqlservr.exe!CLogOp_BaseSetOp::PcnstrDerive() + 0x11a bytes
sqlservr.exe!CLogOpArg::PcnstrDeriveHandler() + 0x18f bytes
sqlservr.exe!CLogOpArg::DeriveGroupProperties() + 0xa9 bytes
sqlservr.exe!COpArg::DeriveNormalizedGroupProperties() + 0x40 bytes
sqlservr.exe!COptExpr::DeriveGroupProperties() + 0x18a bytes
sqlservr.exe!COptExpr::DeriveGroupProperties() + 0x146 bytes
sqlservr.exe!COptExpr::DeriveGroupProperties() + 0x146 bytes
sqlservr.exe!COptExpr::DeriveGroupProperties() + 0x146 bytes
sqlservr.exe!CQuery::PqoBuild() + 0x3cb bytes
sqlservr.exe!CStmtQuery::InitQuery() + 0x167 bytes
sqlservr.exe!CStmtDML::InitNormal() + 0xf0 bytes
sqlservr.exe!CStmtDML::Init() + 0x1b bytes
sqlservr.exe!CCompPlan::FCompileStep() + 0x176 bytes
sqlservr.exe!CSQLSource::FCompile() + 0x741 bytes
sqlservr.exe!CSQLSource::FCompWrapper() + 0x922be bytes
sqlservr.exe!CSQLSource::Transform() + 0x120431 bytes
sqlservr.exe!CSQLSource::Compile() + 0x2ff bytes
ดังนั้นการปิดชื่อในการติดตามสแต็กดูเหมือนว่าจะใช้เวลามากในการเปรียบเทียบสตริง
บทความ KB นี้ระบุว่าDeriveNormalizedGroupProperties
เกี่ยวข้องกับสิ่งที่เคยเรียกว่าการทำให้เป็นมาตรฐานขั้นตอนการของการประมวลผลแบบสอบถาม
สเตจนี้เรียกว่าการโยงหรือ algebrizing และใช้เอาต์พุตแผนภูมิการแยกนิพจน์จากขั้นตอนการแยกวิเคราะห์ก่อนหน้านี้และส่งออกต้นไม้นิพจน์อัลจีไบรซ์ (แผนผังตัวประมวลผลแบบสอบถาม) เพื่อไปข้างหน้าเพื่อการปรับให้เหมาะสม (การเพิ่มประสิทธิภาพแผนเล็กน้อยในกรณีนี้) [อ้างอิง] [อ้างอิง]
ฉันลองอีกหนึ่งการทดสอบ ( สคริปต์ ) ซึ่งเป็นการเรียกใช้การทดสอบเดิมอีกครั้ง แต่ดูสามกรณีที่แตกต่างกัน
- First Name and Last Name สตริงความยาว 10 อักขระที่ไม่มีรายการซ้ำกัน
- First Name and Last Name สตริงความยาว 50 อักขระโดยไม่มีรายการซ้ำกัน
- First Name and Last Name สตริงความยาว 10 ตัวอักษรที่ซ้ำกันทั้งหมด
จะเห็นได้ชัดเจนว่ายิ่งสตริงนานเท่าไหร่สิ่งที่แย่ลงก็ยิ่งได้รับและในทางกลับกันยิ่งซ้ำกันมากขึ้นสิ่งที่ดีกว่าจะได้รับ ตามที่กล่าวไว้ก่อนหน้านี้รายการที่ซ้ำกันไม่ส่งผลต่อขนาดของแผนแคชดังนั้นฉันจึงสันนิษฐานว่าต้องมีกระบวนการในการระบุตัวตนที่ซ้ำกันเมื่อสร้างแผนผังนิพจน์อัลจีไบรซ์เอง
แก้ไข
สถานที่แห่งหนึ่งที่ข้อมูลนี้ถูกนำมาใช้แสดงโดย @Lieven ที่นี่
SELECT *
FROM (VALUES ('Lieven1', 1),
('Lieven2', 2),
('Lieven3', 3))Test (name, ID)
ORDER BY name, 1/ (ID - ID)
เนื่องจากในเวลาคอมไพล์สามารถระบุได้ว่าName
คอลัมน์ไม่มีรายการซ้ำจึงข้ามลำดับโดย1/ (ID - ID)
นิพจน์รองในขณะรัน (การเรียงลำดับในแผนมีเพียงORDER BY
คอลัมน์เดียว) และไม่มีการหารด้วยข้อผิดพลาดเป็นศูนย์ หากมีการเพิ่มรายการที่ซ้ำกันในตารางตัวดำเนินการเรียงลำดับจะแสดงสองลำดับตามคอลัมน์และข้อผิดพลาดที่คาดไว้จะเพิ่มขึ้น