เหตุใด MySQL จึงไม่ใช้ดัชนีในฟิลด์ int ที่ใช้เป็นบูลีน

select * from myTable where myInt

จะไม่แสดง possible_keys ใด ๆ เมื่ออธิบายแบบสอบถามแม้ว่าจะมีดัชนีในฟิลด์ myInt

แก้ไข:
ดัชนีที่เป็นปัญหาไม่ซ้ำกัน


person Senseful    schedule 24.12.2008    source แหล่งที่มา


คำตอบ (4)


เพื่อให้ MySQL ใช้ดัชนี คุณจะต้องเปรียบเทียบฟิลด์ int กับค่าอย่างชัดเจน (เช่น จริง 1)

select * from myTable where myInt = true
person Senseful    schedule 24.12.2008

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

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

บางที MySQL อาจไม่แสดงว่าเป็นคีย์ที่เป็นไปได้เนื่องจากกลไกได้ละทิ้งแนวคิดในการใช้ดัชนีในแผนการดำเนินการ

person matt b    schedule 24.12.2008
comment
ดัชนีไม่ได้จำกัดอยู่เพียงคอลัมน์ที่ไม่ซ้ำกัน โดยพื้นฐานแล้วดัชนีจะค้นหาตารางที่เรียงลำดับ/แฮชตามคอลัมน์ในดัชนี วัตถุประสงค์ของดัชนีคือการบอก RDMS ให้ปรับการค้นหาคอลัมน์บางคอลัมน์ในตารางให้เหมาะสม ดัชนีบนบูลอาจช่วยประสิทธิภาพได้ไม่มากนัก แต่ก็ใช้ได้ - person Bernard Igiri; 24.12.2008
comment
ใช่ ฉันไม่ได้ถามว่ามันถูกต้องหรือไม่ ฉันถามว่ามันมีประโยชน์หรือไม่ ฟิลด์ที่มีการจัดทำดัชนีจะเป็น 0 หรือ 1 เท่านั้น ดังนั้นดัชนีจะมีสองรายการ โดยแต่ละแถวมี N / 2 แถว โดยที่ N = ขนาดของตาราง ถูกต้อง? แล้วประเด็นของการจัดทำดัชนีฟิลด์นี้คืออะไร? - person matt b; 24.12.2008
comment
@matt b: จำนวนสมาชิกไม่ได้กำหนดความจำเพาะ สมมติว่าฟิลด์ถูกตั้งค่าเป็น 1 ในช่วงเวลาเพียงเล็กน้อย: หากใครสนใจที่จะเลือกเฉพาะแถวเหล่านั้น การสแกนทั้งตารางก็คงจะงี่เง่า - person user359996; 07.03.2012

มีหลายปัจจัยที่ต้องพิจารณา

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

SELECT * FROM MyTable WHERE MyInt;

SELECT * FROM MyTable WHERE MyInt != 0;

SELECT * FROM MyTable WHERE MyInt IS TRUE;

SELECT * FROM MyTable WHERE MyInt = TRUE;

อาจมีสูตรอื่นที่เทียบเท่ากัน รายการแรกไม่ใช่ SQL มาตรฐาน (แม้ว่าประเภทของ MyInt จะเป็น BOOLEAN ส่วนรายการอื่นๆ นั้นเป็นมาตรฐาน แต่เครื่องมือเพิ่มประสิทธิภาพควรแปลงชวเลขให้เป็นรูปแบบยาวที่เหมาะสม จากนั้นทำงานเหมือนกับว่ารูปแบบยาวถูกเขียนโดย ผู้ใช้ (หากเครื่องมือเพิ่มประสิทธิภาพไม่ทำเช่นนี้ แสดงว่ามีปัญหาเกิดขึ้นกับเครื่องมือเพิ่มประสิทธิภาพนั้น การสืบค้นควรจะลดลงเป็นรูปแบบมาตรฐานก่อนที่จะตัดสินใจว่าจะประมวลผลการสืบค้นอย่างไร อย่างไรก็ตาม มักจะมีจุดบอดในตัวเพิ่มประสิทธิภาพที่ดีที่สุดด้วยซ้ำ การเรียนรู้วิธีหลีกเลี่ยงสิ่งเหล่านั้นถือเป็นรูปแบบศิลปะและเป็นลักษณะเฉพาะของ DBMS)

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

ในระบบคลังข้อมูล ระบบสามารถออกแบบและกำหนดค่าเพื่อให้สแกนตารางตามลำดับได้อย่างรวดเร็ว ในระบบดังกล่าว หากการเลือกใช้ดัชนีเป็นแบบที่ใช้ดึงแถวมากกว่า 25% การสแกนตารางทั้งหมดจะเร็วกว่าการใช้ดัชนีจริงๆ

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

DBMS บางตัวมีตารางเฉพาะดัชนีเท่านั้น ข้อมูลทั้งหมดอยู่ในดัชนี DBMS อื่นๆ มีกลไกที่คุณสามารถพูดได้ว่า "ดัชนีไม่ซ้ำกันในคอลัมน์ A, B, C อย่างไรก็ตาม ให้รวมคอลัมน์ D และ E ไว้ในข้อมูลด้วย" จากนั้น หากการสืบค้นต้องการข้อมูลจาก A, B, C, D หรือ E (หรือการรวมกันใดๆ) และไม่มีการกรองในคอลัมน์อื่น DBMS จะต้องสแกนดัชนีเท่านั้น ไม่ใช่หน้าตารางด้วย

โดยทั่วไปแล้ว คุณจะได้รับแถวดัชนีจำนวนมากในหนึ่งหน้า อย่างไรก็ตาม สำหรับบางตาราง การอ่านดัชนีอาจจำเป็นต้องอ่านข้อมูลมากกว่าการอ่านแถว พิจารณาตารางการแมปแบบกลุ่มต่อกลุ่มตามแบบฉบับที่มีค่า ID จำนวนเต็มสอง (4 ไบต์) ซึ่งต้องใช้ 8 ไบต์ต่อแถวในหน้าข้อมูล แต่ดัชนีอาจต้องการโอเวอร์เฮด 4-8 ไบต์ (เนื่องจากรายการคีย์ดัชนีเก็บค่า ID สองค่าบวกกับข้อมูลที่จำเป็นในการค้นหาแถวที่เกี่ยวข้องบนดิสก์) ดังนั้น การสแกนดัชนีที่นั่นอาจเกี่ยวข้องกับ I/O ดิสก์มากเป็นสองเท่าของการสแกนข้อมูล แม้ว่าการสแกนดัชนีจะเสร็จสิ้น 'ดัชนีเท่านั้น' ก็ตาม

นี่แทบจะไม่ได้สัมผัสถึงสาเหตุที่เป็นไปได้ในการใช้หรือไม่ใช้ดัชนีเลย

person Jonathan Leffler    schedule 24.12.2008

SQL ของคำถามของคุณดูผิดรูปแบบสำหรับฉัน คุณกำลังมองหาค่าที่ไม่ใช่ค่าว่างของคอลัมน์หรือไม่? สิ่งนี้ควรใช้ดัชนี:

select * from myTable where myInt is not null
person Kieveli    schedule 24.12.2008
comment
MySQL ประเมินนิพจน์ที่ไม่ใช่ศูนย์/ค่าว่างใดๆ ว่าเป็นจริง ตัวอย่างเช่น คำสั่ง SELECT * FROM myTable WHERE 1 เป็นคำสั่งที่ถูกต้อง และจะส่งกลับบันทึกทั้งหมดจากตาราง ในฟิลด์ myInt ฉันกำลังเก็บค่า 0 หรือ 1 ไม่ใช่ค่า NULL และ NOT NULL - person Senseful; 24.12.2008
comment
@eagle: คุณกำลังเก็บค่าที่ไม่ใช่ค่าว่างสองค่าที่แตกต่างกัน (0 และ 1) และ MySQL อนุญาตให้คุณใช้ตัวย่อที่ไม่ได้มาตรฐาน SQL ของคุณจะไม่ย้ายไปยัง DBMS อื่นได้อย่างง่ายดายหากคุณใช้ชวเลข - person Jonathan Leffler; 24.12.2008