ปัญหาการปรับให้เหมาะสม: คีย์ผสมคลัสเตอร์เงื่อนไขแฟล็กและการรวมดัชนี


11

สามตาราง:

product: กับคอลัมน์: ( a, g, ...a_lot_more... )

a: PK, clustered
g: bit-column

main: กับคอลัมน์: ( c, f, a, b, ...a_lot_more... )

c: PK, clustered
f: bit-column
(a, b): UQ 

lookup กับคอลัมน์: ( a, b, c, i )

(a, b): PK, clustered
a: FK to product(a)
c: UQ, FK to main(c)
i: bit-column

ฉันไม่พบดัชนีที่ดีสำหรับการเข้าร่วม:

FROM  
    product
  JOIN 
    lookup
      ON  lookup.a = product.a  
  JOIN
    main
      ON  main.c = lookup.c 
WHERE 
      product.g = 1
  AND
      main.f = 1
  AND 
      lookup.i = 1
  AND lookup.b = 17

ฉันลองใช้ดัชนีครอบคลุมproduct (g, a, ...)และใช้ แต่ไม่ได้ผลลัพธ์ที่น่าประทับใจ

การรวมกันของดัชนีบางอย่างบนlookupตารางสร้างแผนการดำเนินการด้วยการผสานดัชนีโดยมีประสิทธิภาพเพิ่มขึ้นเล็กน้อยจากแผนก่อนหน้านี้

มีชุดค่าผสมที่ชัดเจนที่ฉันขาดหายไปหรือไม่

การออกแบบโครงสร้างใหม่อาจช่วยได้หรือไม่

DBMS คือ MySQL 5.5 และตารางทั้งหมดใช้ InnoDB


ขนาดโต๊ะ:

product: 67K   ,  g applied:    64K 

main:   420K   ,  f applied:   190K

lookup:  12M   ,  b,i applied:  67K 

ลองย้ายตัวกรองเพรดิเคตเป็นตัวเชื่อมและดูว่าเครื่องมือเพิ่มประสิทธิภาพทำสิ่งที่สมเหตุสมผลหรือไม่ ฉันเคยเห็นเครื่องมือเพิ่มประสิทธิภาพของ SQL Server ล้มเหลวก่อนหน้านี้
ConcOfOfTunbridgeWells

ดูเหมือนว่าผลิตภัณฑ์คาร์ทีเซียนเพราะฉันไม่เห็นสิ่งที่เข้าร่วมจากตารางผลิตภัณฑ์ หรือฉันคิดถึงอะไรบางอย่าง ???
RolandoMySQLDBA

@RolandoMySQLDBA: คุณพูดถูก ฉันจะแก้ไขแบบสอบถาม
ypercubeᵀᴹ

คำตอบ:


3

นี่ทำให้ฉันเจ็บปวด ...

ฉันต้องใช้ temp tables กับ InnoDB มาก่อน โหลดด้วยตัวกรองสร้างดัชนีเข้าร่วมตารางชั่วคราวเหล่านี้

ปัญหาที่ฉันคิดคือถ้า InnoDB นั้นมีอัลกอริธึมการเข้าร่วมแบบซ้อนเท่านั้น: ตัวเพิ่มประสิทธิภาพการสืบค้น RDBMS ที่โตแล้วมีประโยชน์มากกว่า สิ่งนี้ขึ้นอยู่กับการพยายามเรียกใช้การโหลดประเภทคลังข้อมูลบน InnoDB

ตารางชั่วคราวลากความซับซ้อนโดยรวมลงในระดับเครื่องมือเพิ่มประสิทธิภาพแบบสอบถาม MySQL ...


ขอบคุณฉันจะลองดู จำนวนหรือแถว (หลังจากใช้เกณฑ์จะไม่ใหญ่ 64K 67K 190K ตามลำดับ) บางทีฉันควรพยายามกำจัดหนึ่งในสามของตาราง ( main) โดย denormalizing ข้อมูลในlookup?
ypercubeᵀᴹ

1
@ypercube: การทำให้เป็นปกติจะทำให้แถวกว้างขึ้นลดความหนาแน่นของหน้าลง = ปัญหาอื่น ๆ
gbn

3

ดูเหมือนผลิตภัณฑ์คาร์ทีเซียน ทำซ้ำเกณฑ์การเข้าร่วม

FROM  
    product
  JOIN 
    lookup
      ON  product.a = lookup.a  
  JOIN
    main
      ON  main.c = lookup.c 
WHERE 
      product.g = 1
  AND
      main.f = 1
  AND 
      lookup.i = 1
  AND lookup.b = 17

คำแนะนำทางเลือก

นี่อาจดูเหมือนแหกคอกและอาจมีกลิ่นเหมือน SQL Anitpattern แต่ตรงนี้มันไป ...

FROM  
    product
JOIN 
    (
        SELECT * FROM lookup
        WHERE i=1 AND b=17
    ) lookup ON product.a = lookup.a  
JOIN
   main ON main.c = lookup.c 
WHERE 
    product.g = 1 AND main.f = 1

ฉันไม่ได้ย้ายproduct.g = 1และmain.f = 1ไปยังแบบสอบถามย่อยเนื่องจากเป็นเขตข้อมูลบิตและจะทำการสแกนตาราง ณ จุดนั้น แม้ว่าเขตข้อมูลบิตจะเป็นดัชนี แต่เครื่องมือเพิ่มประสิทธิภาพข้อความค้นหาจะเพิกเฉยต่อดัชนีดังกล่าว

แน่นอนคุณสามารถเปลี่ยนSELECT * FROM lookupเป็นSELECT a FROM lookupถ้า SELECT ของคุณไม่ต้องการอะไรจากlookup

อาจเกี่ยวข้องกับ a, b ในการเข้าร่วมระหว่างการค้นหาและหลักถ้ามันสมเหตุสมผล

FROM  
    product
  JOIN 
    lookup
      ON  product.a = lookup.a  
  JOIN
    main
      ON  main.a = lookup.a AND main.b = lookup.b
WHERE 
      product.g = 1
  AND
      main.f = 1
  AND 
      lookup.i = 1
  AND lookup.b = 17

หรือใส่กลับ c และเข้าร่วมในสามคอลัมน์ (ดัชนีในสามคอลัมน์ในmainและlookup)

FROM  
    product
  JOIN 
    lookup
      ON  product.a = lookup.a  
  JOIN
    main
      ON main.a = lookup.a
      AND main.b = lookup.b
      AND main.c = lookup.c
WHERE 
      product.g = 1
  AND
      main.f = 1
  AND 
      lookup.i = 1
  AND lookup.b = 17

ขอบคุณ อธิบายแผนแตกต่างกัน แต่มีประสิทธิภาพคล้ายคลึงกัน
ypercubeᵀᴹ

สิ่งที่สำคัญของmain.fและproduct.g? หากความสำคัญเชิงลบของmain.fและproduct.gสำหรับค่าเท่ากับ 1 น้อยกว่า 5% ของแถวของตารางให้เปิดดัชนีmain.fและproduct.gอาจสมเหตุสมผล
RolandoMySQLDBA

ไม่เป็นไรพวกเขาจะถูกจัดทำดัชนีแล้ว หากความสำคัญของmain.fและproduct.gเป็น 2 คุณสามารถทิ้งดัชนีเหล่านั้น
RolandoMySQLDBA

แก้ไขคำถามด้วยขนาดตารางและแถวที่ใช้ (หลังจากใช้เงื่อนไข)
ypercubeᵀᴹ

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