เมื่อจัดการกับฐานข้อมูลขนาดใหญ่ซึ่งทำงานได้ดีขึ้นIN
หรือOR
ใน SQL Where
-clause?
มีความแตกต่างเกี่ยวกับวิธีดำเนินการหรือไม่?
เมื่อจัดการกับฐานข้อมูลขนาดใหญ่ซึ่งทำงานได้ดีขึ้นIN
หรือOR
ใน SQL Where
-clause?
มีความแตกต่างเกี่ยวกับวิธีดำเนินการหรือไม่?
คำตอบ:
ฉันถือว่าคุณต้องการทราบความแตกต่างของประสิทธิภาพระหว่างสิ่งต่อไปนี้:
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% การเพิ่มคำศัพท์เพิ่มเติมทำให้ความแตกต่างมีขนาดใหญ่ขึ้น ผลลัพธ์อาจแตกต่างกันไปในฐานข้อมูลอื่นและข้อมูลอื่น ๆ
IN
วิธีนี้ทำให้การเพิ่มประสิทธิภาพง่ายขึ้นกว่าOR
ข้อที่เกี่ยวข้องทั้งหมด ฉันจะแปลกใจถ้ามีเครื่องยนต์ที่OR
วิธีนั้นเร็วกว่านี้ แต่ฉันไม่แปลกใจที่มีบางครั้งที่ OR ช้ากว่า
OR
ด้วยเสมอได้IN
หรือไม่
วิธีที่ดีที่สุดในการค้นหาคือดูที่แผนดำเนินการ
ฉันลองใช้กับ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')
INLIST ITERATOR
ดำเนินการซึ่งจะเลือกว่ามีดัชนีที่สามารถใช้ได้หรือไม่ แต่ถึงกระนั้นเมื่อฉันลองมันทั้งสองIN
และOR
จบลงด้วยแผนการดำเนินการเดียวกัน
ตัวดำเนินการ OR ต้องการกระบวนการประเมินที่ซับซ้อนมากกว่าโครงสร้าง IN เนื่องจากอนุญาตเงื่อนไขจำนวนมากไม่เพียง แต่เท่ากับ IN
นี่คือสิ่งที่คุณสามารถใช้กับ OR แต่ไม่สามารถใช้งานร่วมกับ IN: ได้มากกว่า มากกว่าหรือน้อยกว่าน้อยกว่าหรือเท่ากับ LIKE และอีกมากมายเช่น oracle REGEXP_LIKE นอกจากนี้พิจารณาว่าเงื่อนไขอาจไม่เปรียบเทียบค่าเดียวกันเสมอไป
สำหรับเครื่องมือเพิ่มประสิทธิภาพข้อความค้นหาจะง่ายต่อการจัดการตัวดำเนินการ IN เพราะเป็นเพียงโครงสร้างที่กำหนดตัวดำเนินการ OR ในหลาย ๆ เงื่อนไขด้วย = ตัวดำเนินการในค่าเดียวกัน หากคุณใช้ตัวดำเนินการ OR เครื่องมือเพิ่มประสิทธิภาพอาจไม่พิจารณาว่าคุณกำลังใช้ตัวดำเนินการ = บนค่าเดียวกันเสมอและหากมันไม่ทำงานอย่างละเอียดมากขึ้นและซับซ้อนมากขึ้นก็อาจไม่รวมว่าอาจมีเพียง = โอเปอเรเตอร์สำหรับค่าเดียวกันในทุกเงื่อนไขที่เกี่ยวข้องพร้อมกับคำนำหน้าของวิธีการค้นหาที่ปรับให้เหมาะสมที่สุดเช่นการค้นหาแบบไบนารีที่กล่าวถึงแล้ว
[แก้ไข] อาจเป็นเครื่องมือเพิ่มประสิทธิภาพอาจไม่ใช้กระบวนการประเมินผลที่ได้รับการปรับให้เหมาะสม แต่สิ่งนี้ไม่ได้ยกเว้นว่าจะเกิดขึ้นเพียงครั้งเดียว (ด้วยการอัปเกรดเวอร์ชันฐานข้อมูล) ดังนั้นหากคุณใช้ตัวดำเนินการ OR ที่เพิ่มความประณีตอย่างเหมาะสมจะไม่ถูกใช้ในกรณีของคุณ
ฉันคิดว่า oracle ฉลาดพอที่จะแปลงสิ่งที่มีประสิทธิภาพน้อยลง ดังนั้นฉันคิดว่าคำตอบควรขึ้นอยู่กับความสามารถในการอ่านของแต่ละคน (ที่ฉันคิดว่ามันIN
ชนะอย่างชัดเจน)
OR
ทำให้รู้สึก (จากมุมมองการอ่าน) เมื่อมีค่าน้อยกว่าที่จะเปรียบเทียบ
IN
มีประโยชน์โดยเฉพาะอย่างยิ่ง เมื่อคุณมีแหล่งที่มาแบบไดนามิกซึ่งคุณต้องการเปรียบเทียบค่า
อีกทางเลือกหนึ่งคือใช้JOIN
กับตารางชั่วคราว
ฉันไม่คิดว่าประสิทธิภาพจะเป็นปัญหาหากคุณมีดัชนีที่จำเป็น
ฉันทำแบบสอบถาม SQL ในจำนวน OR (350) Postgres ทำมัน437.80ms
ตอนนี้ใช้ใน:
23.18ms