ฉันมีฐานข้อมูล sqlite ที่มีสองตารางแต่ละแถวมี 50,000 แถวมีชื่อ (คน) ปลอม ฉันได้สร้างแบบสอบถามง่ายๆเพื่อค้นหาจำนวนชื่อที่มี (ชื่อที่กำหนด, ชื่อกลาง, นามสกุล) ที่ใช้ร่วมกันสำหรับทั้งสองตาราง:
select count(*) from fakenames_uk inner join fakenames_usa on fakenames_uk.givenname=fakenames_usa.givenname and fakenames_uk.surname=fakenames_usa.surname and fakenames_uk.middleinitial=fakenames_usa.middleinitial;
เมื่อไม่มีดัชนียกเว้นในคีย์หลัก (ไม่เกี่ยวข้องกับแบบสอบถามนี้) มันจะทำงานอย่างรวดเร็ว:
[james@marlon Downloads] $ time sqlite3 generic_data_no_indexes.sqlite "select count(*) from fakenames_uk inner join fakenames_usa on fakenames_uk.givenname=fakenames_usa.givenname and fakenames_uk.surname=fakenames_usa.surname and fakenames_uk.middleinitial=fakenames_usa.middleinitial;"
131
real 0m0.115s
user 0m0.111s
sys 0m0.004s
แต่ถ้าฉันเพิ่มดัชนีลงในสามคอลัมน์ในแต่ละตาราง (ดัชนีทั้งหมดหกรายการ):
CREATE INDEX `idx_uk_givenname` ON `fakenames_uk` (`givenname` )
//etc.
จากนั้นมันจะทำงานช้าลงอย่างเจ็บปวด:
[james@marlon Downloads] $ time sqlite3 generic_data.sqlite "select count(*) from fakenames_uk inner join fakenames_usa on fakenames_uk.givenname=fakenames_usa.givenname and fakenames_uk.surname=fakenames_usa.surname and fakenames_uk.middleinitial=fakenames_usa.middleinitial;"
131
real 1m43.102s
user 0m52.397s
sys 0m50.696s
มีการสัมผัสหรือเหตุผลในการนี้หรือไม่?
นี่คือผลลัพธ์ของEXPLAIN QUERY PLAN
เวอร์ชันที่ไม่มีดัชนี:
0|0|0|SCAN TABLE fakenames_uk
0|1|1|SEARCH TABLE fakenames_usa USING AUTOMATIC COVERING INDEX (middleinitial=? AND surname=? AND givenname=?)
นี่คือกับดัชนี:
0|0|0|SCAN TABLE fakenames_uk
0|1|1|SEARCH TABLE fakenames_usa USING INDEX idx_us_middleinitial (middleinitial=?)
SELECT c FROM t WHERE a=1 AND b=2
ดัชนีt(a,b,c)
จะครอบคลุม แต่t(a,b)
ไม่ใช่ ประโยชน์ของดัชนีครอบคลุมคือผลการสืบค้นทั้งหมดสามารถดึงออกมาจากดัชนีได้โดยตรงในขณะที่ดัชนีที่ไม่ครอบคลุมจะค้นหาแถวที่เกี่ยวข้องได้อย่างรวดเร็ว แต่ก็ยังจำเป็นต้องอ้างอิงข้อมูลตารางหลักเพื่อเลือกค่า
middleinitial
,surname
และgivenname
)?