มีประสิทธิภาพมากขึ้นคืออะไรส่วนคำสั่งหรือการรวมกับตารางล้านบวกแถว?


17

เราเรียกใช้เว็บไซต์ที่มีแถว 250 มม. ในหนึ่งตารางและในอีกตารางหนึ่งที่เราเข้าร่วมเพื่อการค้นหาส่วนใหญ่จะมีแถวที่ต่ำกว่า 15 มม.

โครงสร้างตัวอย่าง:

MasterTable (Id, UserId, Created, Updated...) -- 15MM Rows
DetailsTable (Id, MasterId, SomeColumn...) -- 250MM Rows
UserTable (Id, Role, Created, UserName...) -- 12K Rows

เราต้องทำแบบสอบถามสองสามข้อกับตารางเหล่านี้เป็นประจำ หนึ่งคือสถิติโลภสำหรับผู้ใช้ฟรี (ผู้ใช้ฟรี ~ 10k)

Select Count(1) from DetailsTable dt 
join MasterTable mt on mt.Id = dt.MasterId 
join UserTable ut on ut.Id = mt.UserId 
where ut.Role is null and mt.created between @date1 and @date2

ปัญหาคือแบบสอบถามนี้บางครั้งจะใช้เวลาแช่งนานเนื่องจากความจริงที่ว่าการรวมเกิดขึ้นนานก่อนที่

ในกรณีนี้มันจะฉลาดกว่าถ้าใช้ wheres แทนที่จะเข้าร่วมหรืออาจเป็นไปได้where column in(...)?


1
ฐานข้อมูลและรุ่นใด
Leigh Riffel

1
คุณลองทั้งสองวิธีแล้วหรือยัง
gbn

ถ้านี่คือ Oracle ฉันจะสร้างดัชนีตามฟังก์ชั่นสำหรับ UserTable บน NVL2 (บทบาท, NULL, ID) แต่ดูเหมือนว่าฐานข้อมูลอื่น
Leigh Riffel

คำตอบ:


20

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

ไวยากรณ์ JOIN ชัดเจนมีความชัดเจนและคลุมเครือน้อยลง (ดูลิงก์ด้านล่าง)

ตอนนี้ JOIN-before-WHERE เป็นการประมวลผลเชิงตรรกะไม่ใช่การประมวลผลที่เกิดขึ้นจริงและเครื่องมือเพิ่มประสิทธิภาพที่ทันสมัยนั้นฉลาดพอที่จะตระหนักถึงสิ่งนี้

ปัญหาของคุณที่นี่น่าจะเป็นดัชนีมากที่สุด

กรุณาแสดงดัชนีและกุญแจทั้งหมดให้เราในตารางเหล่านี้ และแผนแบบสอบถาม

หมายเหตุ: คำถามนี้จะปิดใน StackOverflow เนื่องจากการทำซ้ำโดยตอนนี้ ... COUNT (1) vs COUNT (*) เป็นอีกตำนานที่ถูกจับเช่นกัน


2
มันไม่ใช่ความจริงเสมอว่าจะไม่มีความแตกต่างระหว่างjoinและwhereข้อ ฉันปรับข้อความค้นหาที่ใช้เวลานานให้เหมาะสมตลอดเวลาและบางครั้งข้อความค้นหาที่ใช้whereประโยคจะทำงานได้ดีกว่าข้อความค้นหาที่ใช้joinโดยปัจจัยสูงสุดถึง 70 เท่า ถ้ามันเป็นสิ่งที่เรียบง่ายและตรงไปตรงมาชีวิตจะเป็นรุ้งและยูนิคอร์นทั้งหมด และนี่ไม่เกี่ยวกับเอ็นจิ้นที่คลุมเครือแบบโบราณ - ตอนนี้ฉันกำลังดูข้อได้เปรียบ 70x whereใน SQL 2012
ajeh

ยิ่งไปกว่านั้นฉันมักจะสังเกตเห็นแผนเดียวกันที่แน่นอนจากทั้งสองวิธีและแยกแบบสอบถามให้ทำงานเหมือนกันทุกประการแต่เมื่อwhereแบบสอบถามย่อยทำงานในชุดข้อมูลขนาดใหญ่มันควรจะเป็นส่วนหนึ่งของมัน joinแบบสอบถาม SQL ไม่ได้ดำเนินการในสุญญากาศ - พวกเขาจะได้รับผลกระทบจากส่วนที่เหลือของเซิร์ฟเวอร์และบ่อยครั้งที่whereคำสั่งแบบสอบถามค่าโดยสารค่อนข้างดีซึ่งเป็นที่น่ารำคาญเพราะjoinไวยากรณ์เป็นจริงสะอาดกว่ามาก
ajeh

3
@ajeh: ฉันอยากจะแนะนำว่าประสบการณ์ของคุณไม่ธรรมดามาก คุณมีปัญหาที่ใหญ่กว่ากับข้อความค้นหาหากคุณมี x70 ที่แตกต่าง: มันง่ายมาก
gbn

5

คุณต้อง refactor แบบสอบถามทั้งหมด

ลองทำคำสั่ง WHERE ก่อนหน้านี้และเข้าร่วมในภายหลัง

Select Count(1) from DetailsTable dt
join (Select UserId,Id FROM MasterTable where
created between @date1 and @date2) mt on mt.Id = dt.MasterId 
join (Select Id FROM UserTable WHERE Role is NULL) ut
on ut.Id = mt.UserId;

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

ฉันได้รับแนวคิดนี้จากวิดีโอ YouTubeนี้

ฉันลองใช้หลักการจากวิดีโอในคำถามที่ซับซ้อนมากใน StackOverflow และได้รับเงินรางวัล 200 แต้ม

@gbn ที่กล่าวถึงทำให้แน่ใจว่าคุณมีดัชนีที่ถูกต้อง ในกรณีนี้โปรดจัดทำดัชนีคอลัมน์ที่สร้างใน MasterTable

ให้มันลอง !!!

อัพเดท 2011-06-24 22:31 EDT

คุณควรเรียกใช้แบบสอบถามเหล่านี้:

SELECT COUNT(1) AllRoles FROM UserTable;
SELECT COUNT(1) NullRoles FROM UserTable WHERE Role is NULL;

ถ้า NullRoles X 20 <AllRoles (กล่าวอีกนัยหนึ่งถ้า NullRoles น้อยกว่า 5% ของแถวของตาราง) คุณควรสร้างดัชนีที่ไม่ซ้ำกันซึ่งมีบทบาทใน UserTable ไม่เช่นนั้นตารางเต็มของ UserTable ก็น่าจะเพียงพอเนื่องจาก Query Optimizer อาจมีกฎออกมาโดยใช้ดัชนี

อัพเดท 2011-06-25 12:40 EDT

ตั้งแต่ฉันเป็น MySQL DBA วิธีการของฉันในการทำสิ่งต่าง ๆ ไม่จำเป็นต้องเชื่อถือ MySQL Query Optimizer ผ่านแง่ร้ายเชิงบวกและการอนุรักษ์ ดังนั้นฉันจะลอง refactoring แบบสอบถามหรือสร้างดัชนีครอบคลุมที่จำเป็นเพื่อก้าวไปข้างหน้าของ MySQL Query Optimizer นิสัยที่ซ่อนอยู่ คำตอบของ @ gbn นั้นดูเหมือนว่าจะสมบูรณ์มากขึ้นใน SQL Server ซึ่งอาจมี "ความแข็งแรงของจิตใจ" มากขึ้นในการประเมินแบบสอบถาม


0

เรามีตาราง [รายละเอียด] ประมาณ 75 ล้านแถว; ตาราง [Master] ประมาณ 400K แถวและตาราง [Item] ที่เกี่ยวข้องซึ่งมี 7 แถวเสมอและตลอดไป มันเก็บชุดเล็ก ๆ ของ“ หมายเลขรายการ” (1-7) และกำลังสร้างแบบจำลองในรูปแบบกระดาษซึ่งล้านพิมพ์และจัดจำหน่ายทุกเดือน ข้อความค้นหาที่เร็วที่สุดคือคำที่คุณคิดว่าน่าจะเป็นอันดับแรกอย่างน้อยที่สุดเกี่ยวกับการใช้การเข้าร่วมคาร์ทีเซียน IIRC มันเป็นเหมือน:

SELECT m.order_id, i.line_nr, d.Item_amt
FROM Master m, Item i 
INNER JOIN Detail d ON m.order_id = d.order_id

แม้ว่าจะมีลิงก์“ id” แบบลอจิคัลระหว่าง [รายการ] และ [รายละเอียด] CROSS JOIN ทำงานได้ดีกว่า INNER JOIN

RDBMS คือ Teradata ด้วยเทคโนโลยี MPP และ IDR แบบแผนการจัดทำดัชนีคืออะไร ตาราง 7 แถวไม่มีดัชนีเนื่องจาก TABLE SCAN ทำงานได้ดีที่สุดเสมอ

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