0Pricing
SQL Interview Prep · บทเรียน

ประสิทธิภาพของ EXISTS เทียบกับ IN

เมื่อใดที่ EXISTS หยุดค้นหาได้ทันทีและทำงานเร็วกว่า IN ซึ่งเป็นคำถามที่พบบ่อยในการคัดกรองผู้สมัครระดับอาวุโส

ประสิทธิภาพของ EXISTS เทียบกับ IN เป็นบทเรียน SQL Interview Prep ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน SQL Interview Prep และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส SQL Interview Prep มีบทเรียนทั้งหมด 4 บทเรียน

EXISTS ตรวจสอบอะไรจริง ๆ

EXISTS รับซับคิวรีและส่งคืนค่าเป็นจริงทันทีที่ซับคิวรีนั้นสร้างแถวอย่างน้อยหนึ่งแถว โดยไม่สนใจค่าที่ส่งคืน สนใจเพียงว่ามีแถวอยู่หรือไม่

  • เป็นการตรวจสอบแบบบูลีนที่ใช้ใน WHERE
  • เกือบจะเป็นแบบสัมพันธ์กับคิวรีภายนอกเสมอ โดยคิวรีภายในจะอ้างอิงแถวจากคิวรีภายนอก

คำถามคัดกรองสั้น ๆ นี้ปรากฏในการสัมภาษณ์ SQL ระดับกลางถึงอาวุโสแทบทุกครั้ง

คิวรี EXISTS พื้นฐาน

ค้นหาลูกค้าที่ส่งคำสั่งซื้ออย่างน้อยหนึ่งรายการ คิวรีภายในมีความสัมพันธ์กับคิวรีภายนอกผ่าน o.customer_id = c.id และ EXISTS จะเป็นจริงทันทีที่พบรายการสั่งซื้อที่ตรงกันหนึ่งรายการ

สังเกต SELECT 1 ค่าที่เลือกส่งออกมาไม่สำคัญ ดังนั้นวิศวกรส่วนใหญ่จึงเขียน 1 หรือ * ผู้สัมภาษณ์ยอมรับทั้งสองแบบ ตัวปรับปรุงประสิทธิภาพจะไม่สนใจรายการเลือกภายใน EXISTS

SELECT c.name
FROM customers c
WHERE EXISTS (
  SELECT 1 FROM orders o
  WHERE o.customer_id = c.id
);

พฤติกรรมการหยุดตรวจสอบทันที

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

ในทางตรงกันข้าม IN จะสร้างชุดค่าจากซับคิวรีในเชิงแนวคิด แล้วจึงตรวจสอบการเป็นสมาชิก หากชุดภายในมีขนาดใหญ่หรือมีค่าซ้ำจำนวนมาก ความแตกต่างนี้มีความสำคัญ

คิวรีเดียวกันที่ใช้ IN

นี่คือรูปแบบ IN ที่เทียบเท่ากับคิวรีค้นหาลูกค้าที่มีรายการสั่งซื้อ ผลลัพธ์เหมือนกันในเชิงตรรกะ แต่กลไกต่างกัน: ซับคิวรีไม่ได้สัมพันธ์กับคิวรีภายนอก และสร้างรายการรหัสลูกค้าที่คิวรีภายนอกนำไปตรวจสอบ

สำหรับตัวปรับปรุงประสิทธิภาพสมัยใหม่ คิวรีเหล่านี้มักสร้างแผนการดำเนินการเดียวกัน — แต่เมื่อ orders มีขนาดใหญ่และมีค่าซ้ำจำนวนมาก EXISTS อาจทำงานได้ดีกว่า เพราะหยุดทันทีที่พบรายการแรก

SELECT c.name
FROM customers c
WHERE c.id IN (
  SELECT o.customer_id FROM orders o
);

NOT EXISTS ดีกว่า NOT IN

นี่คือบทสรุปสำคัญของบทเรียนทั้งหมด NOT EXISTS เป็นวิธีที่ปลอดภัยในการเขียนการเชื่อมตารางแบบตัดออก ต่างจาก NOT IN ตรงที่ไม่เสียหายเมื่อคิวรีภายในมี NULL

รูปแบบนี้ค้นหาลูกค้าทุกคนที่ไม่มีรายการสั่งซื้อได้อย่างน่าเชื่อถือ แม้ว่า orders.customer_id จะมีค่า NULL อยู่ก็ตาม

SELECT c.name
FROM customers c
WHERE NOT EXISTS (
  SELECT 1 FROM orders o
  WHERE o.customer_id = c.id
);

เหตุใด NOT EXISTS จึงปลอดภัยเมื่อมี NULL

NOT EXISTS ถามเพียงว่า ซับคิวรีที่สัมพันธ์กับคิวรีภายนอกพบแถวที่ตรงกันหรือไม่ — เป็นคำตอบใช่หรือไม่ที่ชัดเจน ค่า NULL ใน customer_id จะไม่ทำให้ o.customer_id = c.id เป็นจริง ดังนั้นจึงไม่ตรงกันและไม่ทำให้ตรรกะเสียหาย

เปรียบเทียบกับ NOT IN ซึ่งเมื่อมี NULL ในรายการ จะบังคับให้ผลเป็น UNKNOWN และตัดทุกแถวออก นี่คือเหตุผลที่ผู้สัมภาษณ์ระดับอาวุโสชอบใช้ NOT EXISTS สำหรับการเชื่อมตารางแบบตัดออก

กรณีที่ IN ดีกว่าอย่างแท้จริง

ควรพิจารณาอย่างสมดุล — IN ไม่ได้แย่กว่าเสมอไป เมื่อซับคิวรีส่งคืนรายการขนาดเล็ก คงที่ และไม่มีค่าซ้ำ IN จะอ่านง่ายและทำงานรวดเร็ว:

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

คิวรีด้านล่างเป็นรูปแบบมาตรฐานอย่างสมบูรณ์ การเลือกใช้ EXISTS ในกรณีนี้ถือเป็นการออกแบบเกินความจำเป็น

SELECT name
FROM products
WHERE category_id IN (
  SELECT id FROM categories WHERE active = true
);

คำตอบสมัยใหม่ที่ตรงไปตรงมา

ตัวปรับปรุงประสิทธิภาพที่พัฒนาแล้ว (โพสต์เกรส, SQL Server รุ่นล่าสุด และ MySQL) มักเขียน IN และ EXISTS ใหม่ให้เป็นแผนการเชื่อมตารางแบบกึ่งหนึ่งแผนเดียวกัน ดังนั้นสำหรับการตรวจสอบการเป็นสมาชิกแบบเป็นจริงทั่วไป ประสิทธิภาพจึงมักเท่ากัน

ความแตกต่างที่ยังมีความสำคัญ:

  • NOT IN เทียบกับ NOT EXISTS — ความถูกต้องเมื่อมี NULL ซึ่งเป็นประเด็นจริง ไม่ใช่แค่เรื่องความเร็ว
  • ตารางภายในที่มีขนาดใหญ่มากหรือไม่มีดัชนี — EXISTS จะหยุดตรวจสอบทันทีที่พบผลลัพธ์

EXISTS เทียบกับ JOIN สำหรับการมีอยู่

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

ดังนั้นสำหรับการตรวจสอบเพียงว่ามีอยู่หรือไม่ EXISTS จึงสะอาดกว่า JOIN ... DISTINCT ให้ใช้การเชื่อมตารางเมื่อคุณต้องการคอลัมน์จากอีกตารางจริง ๆ

SELECT DISTINCT c.name
FROM customers c
JOIN orders o ON o.customer_id = c.id;

ดัชนีคือปัจจัยชี้เป็นชี้ตาย

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

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

CREATE INDEX idx_orders_customer_id
  ON orders (customer_id);

ประโยคเด็ดสำหรับการสัมภาษณ์

ตอบว่า: "EXISTS เป็นการตรวจสอบแบบบูลีนที่สัมพันธ์กับคิวรีภายนอก และหยุดตรวจสอบทันทีที่พบแถวแรกที่ตรงกัน ส่วน IN จะตรวจสอบการเป็นสมาชิกของรายการค่า สำหรับการตรวจสอบแบบเป็นจริง ตัวปรับปรุงประสิทธิภาพสมัยใหม่มักสร้างแผนการเชื่อมตารางแบบกึ่งหนึ่งเดียวกัน ความแตกต่างที่แท้จริงคือ NOT EXISTS เทียบกับ NOT IN: NOT EXISTS ปลอดภัยเมื่อมี NULL ดังนั้นผมจึงเลือกใช้สำหรับการเชื่อมตารางแบบตัดออก และตรวจสอบให้แน่ใจว่าคอลัมน์ที่ใช้สร้างความสัมพันธ์มีดัชนี"

ตรวจสอบอย่างรวดเร็ว

แก่นสำคัญของการอภิปรายเรื่อง EXISTS เทียบกับ IN

สรุปทบทวน

สรุปเรื่อง EXISTS เทียบกับ IN:

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

เพียงเท่านี้ก็จบหลักสูตรเจาะลึกเรื่องซับคิวรี

คำถามที่พบบ่อย

บทเรียน “ประสิทธิภาพของ EXISTS เทียบกับ IN” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “ประสิทธิภาพของ EXISTS เทียบกับ IN” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส SQL Interview Prep ให้อัปเกรดเป็น CoddyKit PRO คอร์ส SQL Interview Prep มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “ประสิทธิภาพของ EXISTS เทียบกับ IN”

เมื่อใดที่ EXISTS หยุดค้นหาได้ทันทีและทำงานเร็วกว่า IN ซึ่งเป็นคำถามที่พบบ่อยในการคัดกรองผู้สมัครระดับอาวุโส คุณปฏิบัติ SQL Interview Prep ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน SQL Interview Prep หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน SQL Interview Prep บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน

บทเรียน “ประสิทธิภาพของ EXISTS เทียบกับ IN” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน SQL Interview Prep นี้ได้ไหม

ได้ บทเรียน SQL Interview Prep ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. คิวรีย่อยแบบสเกลาร์ใน SELECT และ WHERE
  2. คิวรีย่อยในส่วน FROM (ตารางที่ได้มา)
  3. คิวรีย่อยแบบ IN, ANY และ ALL
  4. ประสิทธิภาพของ EXISTS เทียบกับ IN
← กลับไปที่ SQL Interview Prep