ใน MySQL ลำดับของคอลัมน์ในส่วนคำสั่ง WHERE มีผลต่อประสิทธิภาพการค้นหาหรือไม่


38

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

แบบสอบถามในคำถามฉันมีสามANDในอนุประโยค

คำสั่งของอนุประโยคมีความสำคัญหรือไม่?

เช่นในถ้าฉันใส่ข้อ ASI_EVENT_TIME ก่อน (เนื่องจากจะลบผลลัพธ์ส่วนใหญ่ออกจากส่วนคำสั่งใด ๆ

จะปรับปรุงเวลาทำงานของแบบสอบถามหรือไม่

ค้นหา:

SELECT DISTINCT  activity_seismo_info.* 
FROM `activity_seismo_info` 
WHERE 
    activity_seismo_info.ASI_ACTIVITY_ID IS NOT NULL  AND 
    activity_seismo_info.ASI_SEISMO_ID IN (43,44,...,259) AND 
    (
        activity_seismo_info.ASI_EVENT_TIME>='2011-03-10 00:00:00' AND 
        activity_seismo_info.ASI_EVENT_TIME<='2011-03-17 23:59:59'
    ) 

ORDER BY activity_seismo_info.ASI_EVENT_TIME DESC

อธิบายคำค้นหา:

+----+-------------+---------+-------+---------------------------+--------------+---------+------+-------+-----------------------------+ 
| id | select_type | table   | type  | possible_keys             | key          | key_len | ref  | rows  | Extra                       |
+----+-------------+---------+-------+---------------------------+--------------+---------+------+-------+-----------------------------+ 
|  1 | SIMPLE      | act...o | range | act...o_FI_1,act...o_FI_2 | act...o_FI_1 | 5       | NULL | 65412 | Using where; Using filesort |
+----+-------------+---------+-------+---------------------------+--------------+---------+------+-------+-----------------------------+

โดยใช้:

PHP 5.2

MySQL 5.0.51a-3ubuntu5.4

ขับเคลื่อน 1.3

Symfony 1.2.5


คำสั่งซื้ออาจจะใช้เวลานานมาก "การใช้ชุดไฟล์" อาจช้ามาก ฉันพบว่าการสั่งซื้อในตรรกะของแอปพลิเคชันนั้นเร็วกว่าการใช้ ORDER BY มาก
maclema

ฉันถามคำถามเดียวกันนี้สักครู่ (ก่อนหน้าเว็บไซต์นี้) ใน stackoverflow ตรวจสอบลิงก์สำหรับคำตอบที่ฉันได้รับ stackoverflow.com/questions/3805863/…
Scott

2
@maclema - ยกเว้นว่าแอปพลิเคชันของคุณทำงานบนเครื่องที่เร็วกว่าฐานข้อมูลของคุณการยืนยันของคุณนั้นไม่จริงแน่นอนไม่ต้องพูดถึงภาระที่ไม่มีจุดหมายของตรรกะการเรียงลำดับทั้งหมดในแอปพลิเคชันของคุณ order byเป็นของในฐานข้อมูล
แจ็คดักลาส

คำตอบ:


24

ฉันไม่คิดเช่นนั้น. เครื่องมือเพิ่มประสิทธิภาพการสืบค้นควรฉลาดพอ

คุณสามารถลองจัดเรียงคำสั่ง WHERE ใหม่และดูว่าคำอธิบายอธิบายคุณเหมือนกันในแต่ละกรณี


เกี่ยวกับสิ่งที่สามารถทำได้เพื่อเพิ่มประสิทธิภาพการค้นหานี้: มีดัชนีใน ASI_EVENT_TIME หรือไม่ (นี่เป็นสิ่งสำคัญที่สุดที่ฉันคิดว่าสำหรับคำถามนี้ขณะที่คุณเรียงลำดับผลลัพธ์ด้วย)

มีดัชนีในอีกสองฟิลด์ (ASI_SEISMO_ID และ ASI_ACTIVITY_ID) หรือไม่

มันจะมีประโยชน์ถ้าคุณโพสต์โครงสร้างตาราง


ฉันไม่เคยคิดที่จะสร้างดัชนีของเหตุการณ์ครั้ง ฉันจะลองในวันพรุ่งนี้โดยใช้ db db และดูว่ามีความแตกต่างที่เห็นได้ชัดเจนหรือไม่
Patrick

@Patrick สมมติว่าแบบสอบถามอื่น ๆ ทั้งหมดที่จะใช้ดัชนีนี้กำลังเรียงลำดับวันที่นี้ตามลำดับจากมากไปหาน้อยคุณต้องการสั่งซื้อคีย์ดัชนี (activity_seismo_info.ASI_EVENT_TIME) ตามลำดับจากมากไปหาน้อยเช่นกัน
Matt M

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

@ แพทริคคุณพูดถูก สมองของฉันติดอยู่ในที่ดินของ SQL Server คุณสามารถระบุลำดับการจัดเรียงใน MySQL และมันจะแยก แต่มันจะถูกละเว้น ดัชนีทั้งหมดจะเรียงตามลำดับจากน้อยไปมากใน MYSQL ขอโทษสำหรับความสับสน.
Matt M

13

จากเอกสาร :

หากตารางมีดัชนีหลายคอลัมน์คำนำหน้าซ้ายสุดของดัชนีสามารถใช้โดยเครื่องมือเพิ่มประสิทธิภาพเพื่อค้นหาแถว ตัวอย่างเช่นหากคุณมีดัชนีสามคอลัมน์บน (col1, col2, col3) คุณจะสามารถจัดทำดัชนีความสามารถในการค้นหาบน (col1), (col1, col2) และ (col1, col2, col3)

MySQL ไม่สามารถใช้ดัชนีได้หากคอลัมน์ไม่ได้เป็นคำนำหน้าซ้ายสุดของดัชนี

ดังนั้นใช่มันควรจะเป็นเช่นเดียวกับคำสั่งของคอลัมน์ในส่วนดัชนีสารประกอบ


4
หากตารางมีดัชนีหลายคอลัมน์การเลือกคอลัมน์จากเรื่องด้านซ้าย - แต่ลำดับที่คุณเลือกนั้นไม่สำคัญ ดังนั้นหากคุณมีดัชนี a, b, c และคุณWHERE c = 'foo' AND a = 'bar' AND b = 'foobar'และดัชนียังคงมีสิทธิ์ใช้งาน
texelate

10

ไม่มันไม่สำคัญ

เครื่องมือเพิ่มประสิทธิภาพจะทำการแปลงอย่างง่าย ๆ ทันทีหลังจากแยกวิเคราะห์ SQL - นี่คือหนึ่งในนั้น


8

ที่ใด foo และแถบ

ปรับให้เหมาะสมเช่นเดียวกับ

ที่แถบและ foo

อย่างไรก็ตาม

WHERE # 1 ไม่เหมือนกันและ # 2 ไม่เท่ากัน

ไม่สามารถปรับทั้งสองส่วนให้เหมาะสม ตัวอย่างเช่น,

ที่อยู่ระหว่าง 1 และ 3 และ b> 17

ไม่สามารถใช้ประโยชน์จาก INDEX (a, b) หรือ INDEX (b, a) ได้ดี

หากต้องการวลีมันแตกต่างกันการทดสอบ '=' ใด ๆ และเข้าด้วยกันในส่วนคำสั่ง WHERE จะถูกใช้ก่อนจากนั้นจึงสามารถจัดการหนึ่งที่ไม่ใช่ - '=' (IN, BETWEEN,> และอื่น ๆ ) ไม่สามารถเพิ่มประสิทธิภาพได้มากกว่าหนึ่งอย่าง

ข้อความค้นหาของคุณมี 3 ข้อดังกล่าว

ตามที่ปรากฎออกมา INDEX (EVENT_TIME) น่าจะมีประโยชน์มากที่สุด - มันจะช่วยให้กับหนึ่งใน ANDs และมันอาจถูกใช้เพื่อหลีกเลี่ยง "filesort" สำหรับ ORDER BY

หากไม่มีแถวที่ซ้ำกัน (ทำไม heck จะมี?) ให้กำจัด DISTINCT นั่นทำให้เกิดความพยายามมากขึ้น

โปรดระบุตารางแสดง SHOW และสถานะตารางแสดงเมื่อถามคำถามเกี่ยวกับประสิทธิภาพ

ปรับปรุง ... เวอร์ชั่นใหม่ (เช่น MySQL 5.7) สามารถในบางสถานการณ์การรักษาเกือบเหมือนIN( list of constants ) =หากต้องการเล่นอย่างปลอดภัยให้ยึดตามคำสั่งนี้ (แต่ละส่วนเป็นตัวเลือก):

  1. =จำนวนใด ๆ
  2. INsบางส่วน
  3. มากที่สุดช่วงหนึ่ง

1

MySQL ที่ doc เพิ่มประสิทธิภาพพูดว่า:

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

  • ...

  • สำหรับตารางในแต่ละเข้าร่วมเป็นง่าย WHEREมีการก่อสร้างที่จะได้รับอย่างรวดเร็วที่การประเมินผลสำหรับตารางและยังข้ามแถวโดยเร็วที่สุดเท่าที่เป็นไปได้

  • ดัชนีตารางแต่ละสอบถามและดัชนีที่ดีที่สุดคือใช้จนกว่าเพิ่มประสิทธิภาพเชื่อว่ามันมีประสิทธิภาพมากขึ้นเพื่อใช้ตารางการสแกน ในครั้งเดียวการสแกนถูกใช้โดยพิจารณาจากดัชนีที่ดีที่สุดซึ่งขยายออกไปมากกว่า 30% ของตาราง แต่เปอร์เซ็นต์คงที่ไม่ได้กำหนดตัวเลือกระหว่างการใช้ดัชนีหรือการสแกนอีกต่อไป เครื่องมือเพิ่มประสิทธิภาพมีความซับซ้อนมากขึ้นและประเมินจากปัจจัยเพิ่มเติมเช่นขนาดตารางจำนวนแถวและขนาดบล็อก I / O

วิธีนี้เป็นเหตุผลสำหรับเครื่องมือเพิ่มประสิทธิภาพการค้นหาเพื่อละเว้นวิธีสั่งเราใช้คอลัมน์ในแบบสอบถาม (ไม่เพียง แต่ MySQL แต่ SQL เป็นภาษาที่มีการประกาศและต้องทำสิ่งที่เราต้องการไม่ใช่วิธีที่เราต้องการ)

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


-2

ฟิลด์ใด ๆที่ใช้ในส่วนคำสั่ง WHERE / HAVING ของคุณและมีการเลือกสูง (จำนวนค่าที่ไม่ซ้ำกัน / จำนวนระเบียนทั้งหมด> 10% ~ 20%) จะต้องทำดัชนี

ดังนั้นหากASI_EVENT_TIMEคอลัมน์ของคุณมีค่าที่เป็นไปได้จำนวนมากอันดับแรกให้สร้างดัชนีทั้งหมด จากนั้นตามที่ @ypercube บอกให้ลองจัดเรียงใหม่และดูว่า EXPLAIN บอกอะไรคุณบ้าง ควรอยู่ใกล้ ๆ กันหมด

นอกจากนี้ต้องการให้คุณมีลักษณะที่ดัชนีกรอง SQL LIKE แม้ว่ามันจะไม่ใช่สิ่งที่คุณต้องการคำตอบ แต่คุณยังจะได้เรียนรู้เกี่ยวกับวิธีการจัดทำดัชนีภายใต้ประทุน

* แก้ไข: อ้างอิงลิงค์ด้านล่างในความคิดเห็นเพื่อเรียนรู้เพิ่มเติมเกี่ยวกับการจัดทำดัชนี


8
-1 การทำดัชนีทุกคอลัมน์ไม่ใช่วิธีปฏิบัติที่ดีที่สุด ทุกดัชนีมีค่าใช้จ่ายหลายวิธี ตรวจสอบให้แน่ใจว่าคุณเลือกดัชนีที่ดีซึ่งโดยปกติจะประกอบด้วยหลายคอลัมน์โดยปกติจะเป็นไปตามลำดับการเลือกและความถี่ที่ใช้ นี้อาจจะเป็น SQL Server เป๋ แต่ข้อมูลดัชนียังคงถูกต้อง: sqlskills.com/BLOGS/KIMBERLY/post/...
Eric Humphrey - lotsahelp

@Eric Humphrey +1 สำหรับคำอธิบายและลิงก์ไปยังเว็บไซต์ของ Kimberly
Matt M

คุณจะผิดมีดัชนีในคอลัมน์บางครั้งเจ็บประสิทธิภาพของคุณบนแบบสอบถามเลือก: mysqlperformanceblog.com/2007/08/28/... คุณไม่ควรใช้กฎของหัวแม่มือ: บางครั้งก็ใช้งานได้บางครั้งไม่ได้
sumar

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