มีประสิทธิภาพที่เพิ่มขึ้นในการสร้างดัชนีฟิลด์บูลีนหรือไม่?


104

ฉันกำลังจะเขียนแบบสอบถามที่มีไฟล์WHERE isok=1. ตามความหมายของชื่อisokคือฟิลด์บูลีน (อันที่จริงTINYINT(1) UNSIGNEDคือตั้งค่าเป็น 0 หรือ 1 ตามต้องการ)

มีประสิทธิภาพที่เพิ่มขึ้นในการสร้างดัชนีฟิลด์นี้หรือไม่? เครื่องยนต์ (InnoDB ในกรณีนี้) จะทำงานได้ดีขึ้นหรือแย่ลงในการค้นหาดัชนี?


คำตอบ:


82

ไม่จริง คุณควรคิดว่ามันเหมือนหนังสือ หากหนังสือมีคำเพียง 3 ชนิดและคุณจัดทำดัชนีคำทั้งหมดคุณจะมีหน้าดัชนีจำนวนเท่ากันกับหน้าปกติ

จะมีประสิทธิภาพที่เพิ่มขึ้นหากมีการบันทึกค่าหนึ่งค่าค่อนข้างน้อย ตัวอย่างเช่นหากคุณมี 1,000 ระเบียนและ 10 รายการเป็น TRUE ก็จะมีประโยชน์หากคุณค้นหาด้วยisok = 1

ดังที่ Michael Durrant กล่าวถึงมันยังทำให้การเขียนช้าลง

แก้ไข: การทำซ้ำที่เป็นไปได้: การสร้างดัชนีฟิลด์บูลีน

ในที่นี้จะอธิบายว่าแม้ว่าคุณจะมีดัชนี แต่ถ้าคุณมีบันทึกมากเกินไปก็ไม่ได้ใช้ดัชนี แต่อย่างใด MySQL ไม่ได้ใช้ดัชนีเมื่อตรวจสอบ = 1 แต่ใช้กับ = 0


4
ดูเหมือนว่า "ใช่: 2 - ไม่ใช่: 1" มีใครบางคนคิดผิด แต่ใครล่ะ?
Niet the Dark Absolute

4
สิ่งนี้ไม่ถูกต้องทั้งหมดหากไม่มีดัชนี mySql จำเป็นต้องสแกนทั้งตารางเพื่อค้นหาแถวที่เกี่ยวข้อง
ilanco

4
มิฉะนั้นจะสแกนดัชนีทั้งหมด (ซึ่งส่วนใหญ่นานพอ ๆ กัน)
Michael Koper

1
มันสามารถสร้างความแตกต่าง. เพียงแค่ลดเวลาในการดำเนินการลงครึ่งหนึ่งของแบบสอบถามเพียงแค่เพิ่มดัชนีและการเขียนนั้นหายากและราคาถูกพอที่เราจะไม่สนใจบทลงโทษ เช่นเดียวกับทุกสิ่งอย่าถือว่าวัดผล (เนื่องจากฐานข้อมูลไม่ได้ทำงานอย่างที่คุณคาดหวังอย่างมีเหตุผล)
Eelco

6
ถือว่าการแจกแจงที่เท่ากันระหว่าง TRUE และ FALSE ตามที่ @oucil กล่าวไว้ด้านล่างหากคุณกำลังมองหาค่าบูลีนซึ่งค่อนข้างหายากอาจต้องใช้เวลาสักครู่ ไม่ได้บอกว่าคุณควรจัดทำดัชนีเสมอไป แต่ฉันจะถือว่าลักษณะของข้อมูลของคุณและคำค้นหาของคุณก็มีความสำคัญเช่นกันภายใต้เครื่องมือฐานข้อมูลส่วนใหญ่
mahemoff

118

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

เรามีตารางที่มีประมาณ 4 ล้านแถวเพียงครั้งละประมาณ 1,000 รายการเท่านั้นที่จะมีการตั้งค่าสถานะบูลีนสวิตช์และนั่นคือสิ่งที่เราค้นหา การเพิ่มดัชนีในฟิลด์บูลีนของเราเร่งความเร็วการสืบค้นตามลำดับขนาดมันใช้เวลาจากประมาณ 9+ วินาทีเป็นเสี้ยววินาที


ใช่ในขณะที่คุณควรพยายามทำความเข้าใจ 'เหตุผล' ของสิ่งต่างๆอย่างชัดเจนให้วัดผลควบคู่ไปกับและลองใช้สิ่งต่างๆในชุดข้อมูลจริงของคุณเพื่อดูว่าทฤษฎีของคุณตรงกับพฤติกรรมจริงของ db engine หรือไม่ (คุณจะแปลกใจ ... )
Eelco

8
@Eelco คุณพูดถูก แต่ในกรณีนี้ผลลัพธ์ที่ได้จริงตรงกับทฤษฎีพื้นฐานดี แนวคิดพื้นฐานที่ว่าควรเป็นเพียงเล็กน้อยเท่านั้นที่สมเหตุสมผลก็ต่อเมื่อคุณมีแนวโน้มว่าจะเจอรายการที่ตรงกับการค้นหาของคุณประมาณ 50% จากนั้นในการค้นหา 100 รายการที่ตรงกัน DB ต้องวนซ้ำ 200 รายการ แต่ถ้ารายการตรงเพียง 1% ของเวลาก็จะต้องทำซ้ำ 10,000 รายการ
mahemoff

7
ฉันชอบเวลาที่ผู้คนลองทำสิ่งต่างๆในสนามจริง ๆ และให้การตอบรับเกี่ยวกับประสิทธิภาพแทนที่จะเป็นเพียงปรัชญา
Viktor Joras

WHERE my_col > 0 แทนที่จะmy_col = 1ช่วยเพิ่มความเร็ว
แอรอน

28

ขึ้นอยู่กับแบบสอบถามจริงและการเลือกของชุดค่าผสมดัชนี / แบบสอบถาม

กรณี A : เงื่อนไขWHERE isok = 1และไม่มีอะไรอื่นที่นั่น:

SELECT *
FROM tableX
WHERE isok = 1
  • หากดัชนีมีการเลือกเพียงพอ (บอกว่าคุณมี 1M แถวและมีเพียง 1k เท่านั้นisok = 1) เอ็นจิ้นSQL อาจใช้ดัชนีและเร็วกว่าที่ไม่มี

  • หากดัชนีไม่ได้รับการคัดเลือกเพียงพอ (สมมติว่าคุณมีแถว 1M และมากกว่า 100,000 แถวisok = 1) เอ็นจิ้นSQL อาจไม่ใช้ดัชนีและทำการสแกนตาราง

กรณี B : เงื่อนไขWHERE isok = 1และสิ่งอื่น ๆ :

SELECT *
FROM tableX
WHERE isok = 1
  AND another_column = 17

จากนั้นขึ้นอยู่กับดัชนีอื่น ๆ ที่คุณมี ดัชนีanother_columnอาจจะเลือกได้มากกว่าดัชนีisokที่มีเพียงสองค่าที่เป็นไปได้ ดัชนี(another_column, isok)หรือ(isok, another_column)จะดียิ่งขึ้น


ฉันคิดว่านี่เป็นคำตอบที่ถูกต้องมากกว่าเมื่อเทียบกับคำตอบด้านบน การกระจายของข้อมูลด้วย

11

ขึ้นอยู่กับการกระจายของข้อมูล

ลองนึกภาพว่าฉันมีหนังสือเล่มหนึ่งที่มีหน้าที่พิมพ์อย่างใกล้ชิด 1,000 หน้าและคำเดียวในหนังสือของฉันคือ 'ใช่' และ 'ไม่' ซ้ำแล้วซ้ำอีกและแจกจ่ายแบบสุ่ม หากฉันถูกขอให้วนรอบอินสแตนซ์ทั้งหมดของ 'ใช่' ดัชนีที่อยู่ด้านหลังของหนังสือจะช่วยได้หรือไม่ มันขึ้นอยู่กับ.

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

แต่ถ้ามีก็ให้บอกว่า 'ใช่' เพียง 10 อินสแตนซ์ในหนังสือพันหน้าของฉันและอย่างอื่นก็เป็นเพียงไม่มากนับล้านดังนั้นดัชนีจะช่วยฉันประหยัดเวลาได้มากในการค้นหาอินสแตนซ์ที่ 'ใช่' ทั้งสิบรายการและวนไปรอบ ๆ .

มันเหมือนกันในฐานข้อมูล หากเป็นการแจกแจงแบบ 50:50 ดัชนีจะไม่ช่วยอะไร - เอ็นจินฐานข้อมูลจะดีกว่าเพียงแค่การไถข้อมูลตั้งแต่ต้นจนจบ (การสแกนแบบเต็มตาราง) และดัชนีจะทำให้ฐานข้อมูลใหญ่ขึ้นและ เขียนและอัปเดตช้าลง แต่ถ้าเป็นการแจกแจงแบบ 4000: 1 (ตามoucilในเธรดนี้) การค้นหาดัชนีสามารถเร่งความเร็วได้อย่างมหาศาลหากเป็น 1 ใน 4000 รายการที่คุณกำลังมองหา


5

ไม่ปกติไม่

โดยปกติคุณจะจัดทำดัชนีเขตข้อมูลสำหรับการค้นหาเมื่อมีการเลือก / จำนวนสมาชิกสูง คาร์ดินาลิตี้ของฟิลด์บูลีนต่ำมากในตารางส่วนใหญ่ นอกจากนี้ยังทำให้การเขียนของคุณช้าลงเล็กน้อย


3

อันที่จริงขึ้นอยู่กับแบบสอบถามที่คุณเรียกใช้ แต่โดยทั่วไปจะใช่เช่นเดียวกับการสร้างดัชนีเขตข้อมูลประเภทอื่น ๆ


2

ใช่ดัชนีจะปรับปรุงประสิทธิภาพตรวจสอบผลลัพธ์ของ EXPLAIN ที่มีและไม่มีดัชนี

จากเอกสาร:

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

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


2
ดัชนีให้ข้อมูลจำนวนมากบนฮาร์ดดิสก์และทำให้การเขียนช้าลงดังนั้นคุณจึงไม่เพียงได้รับจากมัน
Michael Koper

1
จริง แต่ในกรณีนี้TINYINT(1) UNSIGNEDคอลัมน์ขนาดของข้อมูลจะเล็ก
ilanco

และค่าใช้จ่ายในการเขียนที่เพิ่มเข้ามาอาจค่อนข้างต่ำ
Eelco

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