ทำไม ORDER BY ไม่ได้อยู่ในมุมมอง


51

ฉันเข้าใจ ว่าคุณ ไม่สามารถมี ORDER BYมุมมอง (อย่างน้อยใน SQL Server 2012 ฉันทำงานด้วย)

ฉันยังเข้าใจว่า "ถูกต้อง" วิธีการจัดเรียงมุมมองคือการวางORDER BYรอบSELECTงบสอบถามมุมมอง

แต่ด้วยความที่ค่อนข้างใหม่สำหรับ SQL เชิงปฏิบัติและมุมมองการใช้งานที่หลากหลายฉันต้องการที่จะเข้าใจว่าเพราะเหตุใดการออกแบบจึงทำเช่นนี้ หากฉันติดตามประวัติอย่างถูกต้องสิ่งนี้จะเกิดขึ้นได้ครั้งหนึ่งและถูกลบออกอย่างชัดเจนจาก SQL Server 2008 และอื่น ๆ (อย่าพูดฉันในรุ่นที่แน่นอน)

อย่างไรก็ตามเหตุผลที่ดีที่สุดที่ฉันสามารถคิดได้ว่าเหตุใด Microsoft จึงลบคุณลักษณะนี้เนื่องจาก "มุมมองเป็นการรวบรวมข้อมูลที่ไม่เรียงลำดับ"

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


2
คำตอบแรกคือจุดที่สมบูรณ์แบบ ฉันอยากจะแนะนำถ้าคุณต้องการสั่งซื้อมุมมองทำไมคุณไม่ทำแค่นี้ เลือก [คอลัมน์] จาก [YourView] สั่งซื้อโดย [คอลัมน์]
Zane

คำตอบสั้น ๆ : "ด้วยเหตุผลเดียวกันกับที่ ORDER BY ไม่ได้อยู่ในตาราง"
ypercubeᵀᴹ

คำตอบ:


38

(มุมมองที่จัดทำดัชนีไว้แน่นอน)

มุมมองไม่เป็นรูปเป็นร่าง - ข้อมูลไม่ถูกจัดเก็บดังนั้นจึงสามารถจัดเรียงได้อย่างไร มุมมองนั้นเหมือนกับขั้นตอนการจัดเก็บที่เพิ่งบรรจุSELECTด้วยโดยไม่มีพารามิเตอร์ ... มันไม่เก็บข้อมูลมันแค่เก็บคำจำกัดความของแบบสอบถาม เนื่องจากการอ้างอิงที่แตกต่างกันไปยังมุมมองอาจต้องการข้อมูลที่เรียงในรูปแบบที่แตกต่างกันวิธีที่คุณทำเช่นเดียวกับการเลือกจากตารางซึ่งเป็นคอลเลกชันแถวที่ไม่เรียงลำดับตามคำจำกัดความคือการรวมคำสั่งด้วย .

นอกจากนี้ยังให้ลึกเข้าไปในประวัติศาสตร์ คุณอาจจะไม่เคยใส่ในมุมมองโดยไม่ต้องนอกจากนี้ยังรวมถึงORDER BY TOPและในกรณีนี้มีการORDER BYกำหนดแถวที่รวมอยู่ด้วยTOPไม่ใช่วิธีที่จะนำเสนอ มันเกิดขึ้นเพียงเพื่อว่าใน SQL Server 2000 ถ้าTOPเป็น100 PERCENTหรือเพิ่มประสิทธิภาพค่อนข้างง่ายและมันก็จบลงด้วยการผลิตแผนมีการจัดเรียงที่ตรงกับที่{some number >= number of rows in the table} TOP/ORDER BYแต่พฤติกรรมนี้ที่ไม่เคยค้ำประกันหรือเอกสาร - มันก็เป็นที่พึ่งเดียวบนจากการสังเกตซึ่งเป็นนิสัยที่ไม่ดี เมื่อ SQL Server 2005 ออกมาพฤติกรรมนี้เริ่ม "แตกหัก" เนื่องจากการเปลี่ยนแปลงในเครื่องมือเพิ่มประสิทธิภาพที่นำไปสู่แผนการที่แตกต่างกันและตัวดำเนินการที่ใช้งาน - เหนือสิ่งอื่นใดTOP / ORDER BYTOP 100 PERCENTจะได้รับการละเว้นสมบูรณ์ถ้ามันเป็น ลูกค้าบางคนบ่นเกี่ยวกับเรื่องนี้อย่างมากดังนั้น Microsoft จึงออกการตั้งค่าสถานะการติดตามเพื่อคืนสถานะการทำงานเก่า ฉันจะไม่บอกคุณว่าธงเป็นเพราะผมไม่ต้องการให้คุณใช้มันและฉันต้องการที่จะให้แน่ใจว่าเจตนาที่ถูกต้อง - ถ้าคุณต้องการเรียงลำดับคาดการณ์ใช้ORDER BYในแบบสอบถามด้านนอก

เพื่อสรุปและอธิบายจุดที่คุณทำไว้ให้มากที่สุด: Microsoft ไม่ได้ลบอะไรเลย พวกเขาทำให้ผลิตภัณฑ์ดีขึ้นและในฐานะที่เป็นผลข้างเคียงพฤติกรรมที่ไม่มีการรับประกันนี้ก็ไม่น่าเชื่อถือน้อยกว่า โดยรวมแล้วฉันคิดว่าผลิตภัณฑ์นั้นดีกว่าสำหรับมัน


ที่นี่มีการกล่าวถึง (ในความคิดเห็น) ที่TOPดำเนินการเคอร์เซอร์เหนือชุดผลลัพธ์ ดังนั้นจึงสามารถมีคำสั่งที่ชัดเจน
Tim Schmelter

@TimSchmelter ที่ไม่ช่วยเมื่อเครื่องมือเพิ่มประสิทธิภาพเห็นTOP 100 PERCENT / ORDER BYและลบออกจากแผนอย่างสมบูรณ์ ลองดู
Aaron Bertrand

มันเป็นเพียงไซเด็น ความคิดเห็นที่เหลือมีดังต่อไปนี้: "เคล็ดลับ SELECT TOP x ถูกกำหนดให้เลิกใช้ใน SQL Server รุ่นในอนาคตดังนั้นจึงเป็นการดีที่สุดที่จะไม่ใช้เลย"
Tim Schmelter

@TimSchmelter มันไม่มีอยู่แล้ว ฉันไม่คิดว่ามันจะหยุดทำงานในเวอร์ชันใหม่เร็ว ๆ นี้เพราะมันจะทำลายรหัสที่มีอยู่มากเกินไป
Aaron Bertrand

2
@ TimSchmelter มีคำสั่งไม่พูดถึงคำสั่งของแถวมันพูดถึงคำสั่งของคอลัมน์ภายในแถว ใน SQL Server โดยทั่วไปเราไม่ได้พูดถึงแถวที่เป็น tuple เนื่องจากการใช้งานทางกายภาพของแถวนั้นชัดเจนมากสำหรับเรา (ตารางจะแสดงรายการคอลัมน์ตามลำดับที่คุณกำหนดไว้)
Aaron Bertrand

9

หากมุมมองได้รับอนุญาตให้เรียงลำดับแล้วผลลัพธ์ของที่นี่ควรเป็นอย่างไร

CREATE VIEW dbo.V1
AS
  SELECT number
  FROM   SomeTable
  ORDER  BY number ASC

GO

CREATE VIEW dbo.V2
AS
  SELECT number
  FROM   SomeTable
  ORDER  BY number DESC

GO

SELECT *
FROM   dbo.V1
       JOIN dbo.V2
         ON V1.number = V2.number 

ฉันไม่เข้าใจประเด็นนี้ แทนที่จะเขียนมุมมองฐานข้อมูลคุณสามารถเขียนแบบสอบถาม SQL ปกติ ดังนั้นสิ่งที่ควรเป็นคำสั่งของผลในกรณีที่? ขอบคุณ
hqt

7

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

อีกเหตุผลหนึ่งที่การจัดเรียงมาพร้อมกับค่าใช้จ่ายด้านประสิทธิภาพดังนั้นทำไมต้องลงโทษผู้ใช้ทุกคนในมุมมองเมื่อผู้ใช้บางคนต้องการการจัดเรียง ..


5

ANSI SQL อนุญาตเฉพาะการORDER BYสืบค้นภายนอกสุดด้วยเหตุผลที่หลากหลายซึ่งเป็นสิ่งที่เกิดขึ้นเมื่อมีการรวมการเลือกย่อย / ดู / CTE เข้ากับตารางอื่นและแบบสอบถามภายนอกมีORDER BYตัวเอง

เซิร์ฟเวอร์ SQL ไม่สนับสนุนในมุมมอง (เว้นแต่คุณจะใช้มันโดยTOP 100 PERCENTที่ฉันคิดว่าเป็นสาเหตุของข้อผิดพลาด)

แม้ว่าคุณจะเรียกจุดบกพร่อง แต่ผลลัพธ์ไม่เคยเชื่อถือได้และการเรียงลำดับไม่ได้ออกมาตามที่คุณคาดหวังเสมอไป

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

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


3

มุมมองทำตัวเหมือนตารางที่เนื้อหาถูกกำหนดโดยผลลัพธ์ของแบบสอบถาม

ตารางไม่มีคำสั่งซื้อ พวกเขาเป็นเพียงถุงแถว

ดังนั้นมุมมองจึงไม่มีคำสั่งซื้อเช่นกัน คุณสามารถจัดเรียงได้โดยเลือกแถวใน ORDER ที่ต้องการ


1
ตาราง ... เป็นเพียงถุงของแถว - และจากนั้น viwes เป็นเพียงถุงเสมือนของแถวเสมือน - มุมมอง "ไม่มี" - เช่นไม่มีข้อมูลที่เก็บไว้สำหรับพวกเขาเลย - พวกเขาเป็นเพียงแค่ "คำจำกัดความที่เก็บไว้ของแบบสอบถาม ถูกประหารชีวิต "โดยทั่วไป
marc_s

1
+1 ความเท่าเทียมกันของตารางและมุมมองดูเหมือนจะเป็นเหตุผลหลักที่ทำให้มุมมองไม่ควรมีคำสั่ง "โดย"
miracle173

1
"ชมทำตัวเหมือนตาราง" ฉันจะบอกว่า "มุมมองทำตัวเหมือนฐานตารางมุมมองเป็นตาราง"
ypercubeᵀᴹ

-2

คำตอบเดียวที่ยังไม่ได้รับคือ "คำสั่งโดย" สามารถรบกวนการผลักดันของภาคแสดงซึ่งอาจส่งผลกระทบต่อประสิทธิภาพการทำงานอย่างมาก

ตัวอย่างคือการมีมุมมองที่สะสมชุดข้อมูลขนาดใหญ่ลงในสรุปบรรทัด 10 บรรทัดที่เรียงลำดับ 10 อันดับแรก:

select * from TopOrderedView; -- Ordered 10 line summary in 5s

สำหรับกรณีเดียวกันกับภาคแสดงที่คาดเดายาก:

select * from TopOrderedView where <condition>; -- Ordered 2 line summary in still 5s

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

การผลักดันควรเกิดขึ้นก่อนการสั่งซื้อโดยเป็นตัวเลือกนักพัฒนาหรือไม่และสามารถเปลี่ยนคำตอบได้ ส่วนใหญ่มักจะผลักดันเป็นเจตนาเชิงตรรกะ

การใช้ "top 100 เปอร์เซนต์" อย่างมีเหตุผลช่วยให้สามารถผลักดันเพรดิเคตได้อย่างไรก็ตามการใช้งานจะไม่สนใจคำสั่ง "โดย" สำหรับกรณีนี้และเอาชนะเจตนา

สำหรับกรณีการใช้งานจริงการประนีประนอมที่ดีจะทำให้เครื่องยนต์ทำการสั่ง "ด้วยการดึง" สิ่งนี้จะอนุญาตให้ระบุ "สั่งซื้อโดย" ภายในมุมมอง (ที่มี 100 เปอร์เซ็นต์สูงสุดหรือไม่มีอันดับสูงสุด) และลำดับนั้นจะใช้เฉพาะเมื่อเลือกมุมมองจากโดยตรงโดยไม่มีคำสั่งที่ชัดเจนโดยไม่มีการรวมไม่มีการรวมไม่มี การดูการโยง ฯลฯ ทั้งสองกรณีที่กล่าวข้างต้นอาจได้รับการสนับสนุนจากรุ่นง่าย ๆ นี้


-6

คุณสามารถสร้างมุมมองที่มีการสั่งซื้อโดยและรักษาลำดับโดยเมื่อสอบถามหลังจาก:

เลือก 99.999999999999 เปอร์เซ็นต์ * จาก ..... สั่งซื้อโดย


1
ทำไมไม่เพียงSELECT TOP 100 PERCENT ...?
Max Vernon

2
@ Max อาจคล้ายกับเคล็ดลับนี้ - นั่นไม่ได้ทำให้เป็นความคิดที่ดี
Aaron Bertrand

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