เมื่อใดจึงควรใช้แบบสอบถามย่อย SQL เทียบกับการรวมมาตรฐาน

ฉันกำลังเขียนข้อความค้นหา SQL ที่เขียนไม่ดีขึ้นมาใหม่และมีการใช้ข้อความค้นหาย่อยมากเกินไป ฉันกำลังมองหาแนวทางปฏิบัติที่ดีที่สุดเกี่ยวกับการใช้ข้อความค้นหาย่อย

ความช่วยเหลือใด ๆ ที่จะได้รับการชื่นชม


person Brad Krusemark    schedule 25.01.2011    source แหล่งที่มา
comment
ไม่ใช่ว่าไม่มีประเด็นสำคัญ แต่ปัญหาก็คือคำถามกว้างเกินกว่าจะตอบได้อย่างสมเหตุสมผล ไม่มีการรับประกันว่าสิ่งที่ใช้ได้กับฐานข้อมูลหนึ่ง (MySQL) จะทำงานเหมือนกันกับอีกฐานข้อมูลหนึ่งทุกประการ กฎที่ง่ายที่สุดคือ ถ้าคอลัมน์จากแบบสอบถามย่อยอยู่ในชุดผลลัพธ์สุดท้าย ให้ใช้ JOIN ซึ่งเป็นวิธีรับข้อมูลจากสองตารางที่เหมาะสมที่สุด มิฉะนั้น แบบสอบถามย่อยก็ใช้ได้ แต่แบบสอบถามย่อยที่เชื่อมโยงกันอาจทำให้เกิดปัญหาได้ (แม้ว่าจะไม่ใช่กับ EXISTS)   -  person OMG Ponies    schedule 26.01.2011
comment
คุณระบุว่ามีการใช้คำค้นหาย่อยมากเกินไปบนพื้นฐานใด ดูเหมือนแปลกที่จะตัดสินใจว่า แล้ว ขอข้อมูลเกี่ยวกับแนวทางปฏิบัติที่ดีที่สุดสำหรับการใช้ข้อความค้นหาย่อย   -  person Larry Lustig    schedule 26.01.2011
comment
อาจซ้ำกันของ Join vs. sub-query   -  person Ciro Santilli 新疆再教育营六四事件ۍ    schedule 12.06.2016
comment
@OMGPonies กฎที่ง่ายที่สุดของคุณตรงกับ AskTom กฎเหล่านั้น (รวม / แบบสอบถามย่อย) มีความหมายแตกต่างกัน * ใช้แบบสอบถามย่อยเมื่อคุณไม่ต้องการคอลัมน์จากตารางที่อ้างอิงในแบบสอบถามย่อย * ใช้การรวมเมื่อคุณต้องการบางคอลัมน์ เลือก * จาก emp โดยที่ deptno ใน (เลือก deptno จาก dept); จะดีกว่าเลือก emp.* จาก emp, dept โดยที่ emp.deptno = dept.deptno; และโปรดจำไว้ว่า แบบสอบถามย่อยไม่สามารถแทนที่ด้วยการเข้าร่วมได้ (และในทางกลับกัน) เนื่องจากมักจะให้ผลลัพธ์เป็นคำตอบที่แตกต่างกัน   -  person ExcessOperatorHeadspace    schedule 14.05.2019


คำตอบ (3)


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

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

หากคุณได้รับข้อผิดพลาดทางไวยากรณ์เนื่องจากตารางดังกล่าวอ้างอิงถึงบางตารางที่อยู่นอกแบบสอบถามย่อย แสดงว่าเป็น dependent subquery

แน่นอนว่ากฎทั่วไปมีข้อยกเว้นบางประการ ตัวอย่างเช่น:

  • เครื่องมือเพิ่มประสิทธิภาพหลายตัวสามารถรับแบบสอบถามย่อยที่ขึ้นต่อกันและค้นหาวิธีการเรียกใช้อย่างมีประสิทธิภาพในฐานะ JOIN ตัวอย่างเช่น แบบสอบถามที่ไม่มีอยู่อาจส่งผลให้เกิดแผนแบบสอบถาม ANTI JOIN ดังนั้นจึงไม่จำเป็นต้องช้ากว่าการเขียนแบบสอบถามด้วย JOIN
  • MySQL มี bug โดยที่แบบสอบถามย่อยอิสระภายในนิพจน์ IN ถูกระบุอย่างไม่ถูกต้องว่าเป็น แบบสอบถามย่อยที่ขึ้นต่อกันและดังนั้นจึงใช้แผนการสืบค้นที่ไม่เหมาะสม เห็นได้ชัดว่าสิ่งนี้ได้รับการแก้ไขแล้วใน MySQL เวอร์ชันใหม่ล่าสุด

หากประสิทธิภาพเป็นปัญหา ให้วัดคำค้นหาเฉพาะของคุณและดูว่าอะไรดีที่สุดสำหรับคุณ

person Mark Byers    schedule 25.01.2011
comment
โดยที่มีความสัมพันธ์กันคุณหมายถึงมีการอ้างอิงไปยังคอลัมน์ในแบบสอบถามภายนอกหรือไม่? - person El Ronnoco; 26.01.2011
comment
เครื่องมือเพิ่มประสิทธิภาพหลายตัวสามารถใช้แบบสอบถามย่อยที่ขึ้นต่อกันและค้นหาวิธีการเรียกใช้อย่างมีประสิทธิภาพ - ฉันเห็นด้วยกับข้อความนี้ และจะลบล้างข้อโต้แย้งทั้งหมดของคุณ กล่าวคือ แบบสอบถามย่อยที่สัมพันธ์กันนั้นไม่ดี ยกเว้นเมื่อพวกมันไม่ได้แย่ - person onedaywhen; 21.09.2011

ไม่มีกระสุนเงินที่นี่ การใช้งานแต่ละครั้งจะต้องได้รับการประเมินอย่างอิสระ มีบางกรณีที่แบบสอบถามย่อยที่สัมพันธ์กันไม่มีประสิทธิภาพเลย แบบสอบถามด้านล่างนี้ควรเขียนเป็น JOIN ดีกว่า

select nickname, (select top 1 votedate from votes where user_id=u.id order by 1 desc)
from users u

ในทางกลับกัน ข้อความค้นหาที่มีอยู่และไม่มีอยู่จะชนะมากกว่า JOIN

select ...
where NOT EXISTS (.....)

ปกติจะเร็วกว่า.

select ...
FROM A LEFT JOIN B
where B.ID is null

แม้ว่าลักษณะทั่วไปเหล่านี้อาจไม่เป็นจริงสำหรับสคีมาและการกระจายข้อมูลใดๆ

person RichardTheKiwi    schedule 25.01.2011

น่าเสียดายที่คำตอบนั้นขึ้นอยู่กับเซิร์ฟเวอร์ sql ที่คุณใช้เป็นอย่างมาก ตามทฤษฎีแล้ว การรวมจะดีกว่าจากมุมมองของทฤษฎีเชิงสัมพันธ์ที่บริสุทธิ์ พวกเขาปล่อยให้เซิร์ฟเวอร์ทำสิ่งที่ถูกต้องภายใต้ประทุนและให้การควบคุมมากขึ้น และในที่สุดก็จะเร็วขึ้นได้ หาก เซิร์ฟเวอร์ได้รับการติดตั้งอย่างดี ในทางปฏิบัติ เซิร์ฟเวอร์ SQL บางตัวทำงานได้ดีกว่าหากคุณหลอกให้เพิ่มประสิทธิภาพการสืบค้นผ่านแบบสอบถามย่อยและสิ่งที่คล้ายกัน

person Wes Hardaker    schedule 25.01.2011
comment
แบบสอบถามย่อยบางรายการสามารถเลื่อนระดับเป็นเข้าร่วมได้ (ขึ้นอยู่กับเซิร์ฟเวอร์) ในกรณีส่วนใหญ่ ฉันพบว่าการรวมเข้ากับหัวของฉันได้ดีกว่า - person ; 26.01.2011
comment
ไม่ หากเซิร์ฟเวอร์ได้รับการติดตั้งอย่างดี เซิร์ฟเวอร์จะจดจำวิธีที่เร็วที่สุดในการดำเนินการ JOIN หรือแบบสอบถามย่อย และสร้างแผนการดำเนินการที่เหมาะสมที่สุด หาก JOIN และแบบสอบถามย่อยเหมือนกันในเชิงพีชคณิต เซิร์ฟเวอร์ที่ใช้งานได้ดีจะสร้างแผนการดำเนินการเดียวกัน - person Larry Lustig; 26.01.2011
comment
ใช่... จริงทั้งหมด หากเซิร์ฟเวอร์ได้รับการติดตั้งอย่างสมบูรณ์แบบ มันจะปรับการสืบค้นที่เสียหายของคุณให้เหมาะสมเช่นกัน ;-) แต่... นั่นคือประเด็นส่วนใหญ่ของฉัน: เซิร์ฟเวอร์ sql เกือบทั้งหมดทำงานได้ดีขึ้นหากคุณสร้างการสืบค้นของคุณตามลักษณะการทำงาน มันเป็นความจริงที่น่าเสียดาย โดยทั่วไป ยิ่งผลิตภัณฑ์มีอายุนานเท่าใดก็ยิ่งมีแนวโน้มว่าจะทำงานได้ดีขึ้นมากขึ้นไม่ว่าคุณจะจัดโครงสร้างการสืบค้นอย่างไรก็ตาม แต่นั่นก็ไม่เป็นความจริงเสมอไป - person Wes Hardaker; 26.01.2011
comment
การรวมจะดีกว่าจากมุมมองทฤษฎีเชิงสัมพันธ์ที่บริสุทธิ์ - เรื่องไร้สาระ พิจารณาว่า SQL ยังไม่สมบูรณ์เชิงสัมพันธ์เกี่ยวกับพีชคณิตของ Codd จนกว่าจะเพิ่มการรองรับแบบสอบถามย่อย - person onedaywhen; 21.09.2011