ทำคอลัมน์ซ้ำเพื่อการสืบค้นที่เร็วขึ้นไหม


30

ชื่อเรื่องไม่สมเหตุสมผล แต่ฉันไม่สามารถคิดชื่อที่ดีกว่าสำหรับปัญหานี้ได้

ฉันมีตารางต่อไปนี้

โครงการ

  • รหัส
  • ชื่อ

ลูกค้า

  • รหัส
  • id_project
  • ชื่อ

การชำระเงิน

  • รหัส
  • id_customer
  • วันที่
  • รวม

เมื่อผู้ใช้เข้าสู่ระบบเขาจะสามารถเข้าถึงโครงการบางอย่างได้ ตอนนี้ฉันต้องการแสดงรายการการชำระเงินทั้งหมดสำหรับโครงการนั้นและควรง่าย:

SELECT FROM payments where id_customer in (SELECT id from customers where id_project = 5)

คำถามของฉันคือ: หากการเพิ่มคอลัมน์ id_project ในตารางการชำระเงินไม่ดีกว่าวิธีนี้จะทำให้การสืบค้นง่ายขึ้นและเร็วขึ้น


1
ดังนั้นการสืบค้นจึงไม่เป็นปัญหาสำหรับ RDBMS รุ่นใหม่ (หรือดีกว่าให้ใช้การเข้าร่วม)
garik

4
เห็นด้วยรับแผนแบบสอบถามสำหรับ subselect VS เข้าร่วมและดูเป็นที่หนึ่งที่ดีกว่า
ออกุสตุ

1
ฉันคิดว่าโพสต์SOนี้น่าดูตั้งแต่ @igor พูดถึงการใช้ JOIN หรือ IN
CoderHawk

คำตอบ:


52

ดูเหมือนว่าคุณกำลังถามว่าdenormalizationทำให้รู้สึก

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

คำตอบคือ "ขึ้นอยู่กับ" เสมอดังนั้นนี่คือกฎง่ายๆของฉัน:

ถ้า ...

  • ปริมาณข้อมูลไม่มาก
  • คุณยังไม่ได้เข้าร่วมมากมาย
  • และ / หรือประสิทธิภาพของฐานข้อมูลไม่ได้เป็นคอขวดในขณะนี้

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

ฉันจะทำให้ผิดปกติเมื่อ ...

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

การเข้าร่วมนั้นรวดเร็วมากกับฮาร์ดแวร์ที่ทันสมัย ​​แต่ก็ไม่เคยว่าง


9

คุณควรเขียนแบบสอบถามเป็น:

SELECT payments.*
FROM   customers
JOIN   payments 
ON     payments.id_customer = customers.id
WHERE  customers.id_project = 5

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

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

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

customer     project      payment
--------     --------     -------
                          pa_id
             pr_id    <-- payment
cu_id    <-- customer     

หรือถ้าเป็นมาตรฐานน้อย (แม้ว่าฉันสงสัยว่าจะมีความจำเป็น):

customer     project      payment
--------     --------     --------
                          pa_id
             pr_id    <-- payment
cu_id    <-- customer 
           `------------- customer    

แน่นอนว่ายังคงลดความเป็นไปได้ของโครงการร่วมกับลูกค้าสองราย ...


3
กฎข้อแรกของประสิทธิภาพ: อย่าใช้ * ในการผลิต!
Brian Ballsun-Stanton

@Brian: จุดที่ถูกต้องมาก และเช่นเดียวกับผลกระทบที่อาจเกิดประสิทธิภาพหลีกเลี่ยง * ในข้อเลือกยังหลีกเลี่ยงปัญหาเกี่ยวกับการสั่งซื้อคอลัมน์ในมุมมองเกี่ยวกับมุมมองใน MSSQL ถ้า sys.depends ได้รับจาก kilter เนื่องจากDROP VIEW+ ถูกนำมาใช้แทนCREATE VIEW ALTER VIEW
David Spillett

@Brian ฉันใส่ * เพื่อความสะดวกในการเขียน
Gabriel Solomon

โครงการนี้เป็นความคิดที่มากขึ้นในฐานะแอปพลิเคชันอิสระที่มีอยู่ในโดเมนและเป็นของลูกค้าที่แตกต่างกันดังนั้นลูกค้าไม่สามารถมีบัญชีเดียวกันในโครงการที่แตกต่างกัน
Gabriel Solomon

4

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

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