IN หรือ OR ในส่วนคำสั่ง SQL


150

เมื่อจัดการกับฐานข้อมูลขนาดใหญ่ซึ่งทำงานได้ดีขึ้นINหรือORใน SQL Where-clause?

มีความแตกต่างเกี่ยวกับวิธีดำเนินการหรือไม่?


การเดาครั้งแรกของฉันคือ OR หรือทำงานได้ดีขึ้นเว้นแต่ว่าโปรแกรม SQL จะแปลง IN ไปเป็น OR เบื้องหลัง คุณเคยเห็นแผนแบบสอบถามของทั้งสองนี้หรือไม่
ราชา

สำเนาที่เป็นไปได้ของประสิทธิภาพของMYSQL หรือ vs
Steve Chambers

คำตอบ:


170

ฉันถือว่าคุณต้องการทราบความแตกต่างของประสิทธิภาพระหว่างสิ่งต่อไปนี้:

WHERE foo IN ('a', 'b', 'c')
WHERE foo = 'a' OR foo = 'b' OR foo = 'c'

ตามคู่มือสำหรับ MySQLหากค่าคงที่จะINเรียงรายการแล้วใช้การค้นหาแบบไบนารี ฉันจะจินตนาการว่าORประเมินพวกเขาทีละคนในลำดับที่ไม่มี ดังนั้นINเร็วกว่าในบางสถานการณ์

วิธีที่ดีที่สุดที่จะรู้คือการทำโปรไฟล์ทั้งในฐานข้อมูลของคุณด้วยข้อมูลเฉพาะของคุณเพื่อดูว่าเร็วกว่าใด

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

SELECT COUNT(*) FROM t_inner WHERE val IN (1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000);
1 row fetched in 0.0032 (1.2679 seconds)

SELECT COUNT(*) FROM t_inner WHERE val = 1000 OR val = 2000 OR val = 3000 OR val = 4000 OR val = 5000 OR val = 6000 OR val = 7000 OR val = 8000 OR val = 9000;
1 row fetched in 0.0026 (1.7385 seconds)

ดังนั้นในกรณีนี้วิธีการใช้หรือจะช้ากว่าประมาณ 30% การเพิ่มคำศัพท์เพิ่มเติมทำให้ความแตกต่างมีขนาดใหญ่ขึ้น ผลลัพธ์อาจแตกต่างกันไปในฐานข้อมูลอื่นและข้อมูลอื่น ๆ


20
หากเครื่องมือเพิ่มประสิทธิภาพมีค่าเกลือพวกเขาควรดำเนินการเหมือนกัน
Janick Bernet

27
@inflagranti: ไม่มีเครื่องมือเพิ่มประสิทธิภาพที่สมบูรณ์แบบน่าเสียดาย เครื่องมือเพิ่มประสิทธิภาพเป็นโปรแกรมที่ซับซ้อนมากและการใช้งานแต่ละอย่างจะมีจุดแข็งและจุดอ่อนของตนเอง นี่คือเหตุผลที่ฉันบอกว่าคุณควรทำโปรไฟล์เกี่ยวกับการใช้งานเฉพาะ ฉันจินตนาการว่าโครงสร้างพิเศษของINวิธีนี้ทำให้การเพิ่มประสิทธิภาพง่ายขึ้นกว่าORข้อที่เกี่ยวข้องทั้งหมด ฉันจะแปลกใจถ้ามีเครื่องยนต์ที่ORวิธีนั้นเร็วกว่านี้ แต่ฉันไม่แปลกใจที่มีบางครั้งที่ OR ช้ากว่า
Mark Byers

2
@MarkByers เครื่องมือเพิ่มประสิทธิภาพไม่สามารถทดแทนหลาย ๆ ครั้งORด้วยเสมอได้INหรือไม่
tymtam

36

วิธีที่ดีที่สุดในการค้นหาคือดูที่แผนดำเนินการ


ฉันลองใช้กับOracleและมันก็เหมือนกันทุกประการ

CREATE TABLE performance_test AS ( SELECT * FROM dba_objects );

SELECT * FROM performance_test
WHERE object_name IN ('DBMS_STANDARD', 'DBMS_REGISTRY', 'DBMS_LOB' );

แม้ว่าเคียวรีจะใช้INแผนปฏิบัติการจะระบุว่าจะใช้OR:

--------------------------------------------------------------------------------------    
| Id  | Operation         | Name             | Rows  | Bytes | Cost (%CPU)| Time     |    
--------------------------------------------------------------------------------------    
|   0 | SELECT STATEMENT  |                  |     8 |  1416 |   163   (2)| 00:00:02 |    
|*  1 |  TABLE ACCESS FULL| PERFORMANCE_TEST |     8 |  1416 |   163   (2)| 00:00:02 |    
--------------------------------------------------------------------------------------    

Predicate Information (identified by operation id):                                       
---------------------------------------------------                                       

   1 - filter("OBJECT_NAME"='DBMS_LOB' OR "OBJECT_NAME"='DBMS_REGISTRY' OR                
              "OBJECT_NAME"='DBMS_STANDARD')                                              

1
จะเกิดอะไรขึ้นใน Oracle หากคุณมีค่ามากกว่า 3 ค่าที่คุณกำลังทดสอบ คุณรู้หรือไม่ว่า Oracle ไม่สามารถทำการเพิ่มประสิทธิภาพการค้นหาแบบไบนารีเช่นเดียวกับ MySQL หรือไม่นั้นทั้งสองกรณีทำงานได้หรือไม่?
Mark Byers

2
@Mark Byers: ฉันลองใช้ข้อความค้นหาเดียวกันโดยมี 10 ค่ายังคงเป็นผลลัพธ์เดียวกัน โปรดทราบว่าเครื่องมือเพิ่มประสิทธิภาพใช้ค่าของฉันเรียงตามตัวอักษร ฉันจะไม่ต้องแปลกใจถ้าออราเคิลได้บางการเพิ่มประสิทธิภาพภายในของตัวกรองที่ ...
ปีเตอร์แลง

5
Oracle ยังมีการINLIST ITERATORดำเนินการซึ่งจะเลือกว่ามีดัชนีที่สามารถใช้ได้หรือไม่ แต่ถึงกระนั้นเมื่อฉันลองมันทั้งสองINและORจบลงด้วยแผนการดำเนินการเดียวกัน
Cheran Shunmugavel

7

ตัวดำเนินการ OR ต้องการกระบวนการประเมินที่ซับซ้อนมากกว่าโครงสร้าง IN เนื่องจากอนุญาตเงื่อนไขจำนวนมากไม่เพียง แต่เท่ากับ IN

นี่คือสิ่งที่คุณสามารถใช้กับ OR แต่ไม่สามารถใช้งานร่วมกับ IN: ได้มากกว่า มากกว่าหรือน้อยกว่าน้อยกว่าหรือเท่ากับ LIKE และอีกมากมายเช่น oracle REGEXP_LIKE นอกจากนี้พิจารณาว่าเงื่อนไขอาจไม่เปรียบเทียบค่าเดียวกันเสมอไป

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

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


6

ฉันคิดว่า oracle ฉลาดพอที่จะแปลงสิ่งที่มีประสิทธิภาพน้อยลง ดังนั้นฉันคิดว่าคำตอบควรขึ้นอยู่กับความสามารถในการอ่านของแต่ละคน (ที่ฉันคิดว่ามันINชนะอย่างชัดเจน)


2

ORทำให้รู้สึก (จากมุมมองการอ่าน) เมื่อมีค่าน้อยกว่าที่จะเปรียบเทียบ INมีประโยชน์โดยเฉพาะอย่างยิ่ง เมื่อคุณมีแหล่งที่มาแบบไดนามิกซึ่งคุณต้องการเปรียบเทียบค่า

อีกทางเลือกหนึ่งคือใช้JOINกับตารางชั่วคราว
ฉันไม่คิดว่าประสิทธิภาพจะเป็นปัญหาหากคุณมีดัชนีที่จำเป็น


-2

ฉันทำแบบสอบถาม SQL ในจำนวน OR (350) Postgres ทำมัน437.80ms

ใช้หรือ

ตอนนี้ใช้ใน:

ใช้ใน

23.18ms


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