Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> MySQL

เร่งความเร็ว COUNT DISTINCT ใน MySQL ด้วย INDEX

คำสั่ง COUNT(DISTINCT column) อาจช้าเมื่อข้อมูลเยอะ เพราะต้องสแกนและจัดกลุ่มค่าที่ไม่ซ้ำทั้งหมด วิธีเร่งความเร็วคือสร้าง INDEX บนคอลัมน์ที่ใช้ใน DISTINCT

ตัวอย่างการใช้งาน

1. สร้างตารางพร้อม INDEX แบบ Composite

mysql> create table DemoTable1905 ( 
    -> FirstName varchar(20), 
    -> LastName varchar(20), 
    -> INDEX F_L_Name(FirstName, LastName) 
    -> ); Query OK, 0 rows affected (0.00 sec)

2. เพิ่มข้อมูลทดสอบ

mysql> insert into DemoTable1905 values('John','Smith'); Query OK, 1 row affected (0.00 sec)
mysql> insert into DemoTable1905 values('John','Doe'); Query OK, 1 row affected (0.00 sec)
mysql> insert into DemoTable1905 values('Adam','Smith'); Query OK, 1 row affected (0.00 sec)
mysql> insert into DemoTable1905 values('John','Doe'); Query OK, 1 row affected (0.00 sec)
mysql> insert into DemoTable1905 values('Chris','Brown'); Query OK, 1 row affected (0.00 sec)
mysql> insert into DemoTable1905 values('Adam','Smith'); Query OK, 1 row affected (0.00 sec)

ข้อมูลทั้งหมด:

mysql> select * from DemoTable1905;
+-----------+----------+
| FirstName | LastName |
+-----------+----------+
| Adam      | Smith    |
| Adam      | Smith    |
| Chris     | Brown    |
| John      | Doe      |
| John      | Doe      |
| John      | Smith    |
+-----------+----------+
6 rows in set (0.00 sec)

3. นับค่า FirstName ที่ไม่ซ้ำ

mysql> select count(distinct FirstName) from DemoTable1905;

ผลลัพธ์:

+---------------------------+
| count(distinct FirstName) |
+---------------------------+
|                         3 |
+---------------------------+
1 row in set (0.00 sec)

ทำไม INDEX ช่วยได้?

  • Index เก็บค่าที่เรียงลำดับแล้ว → MySQL สแกน Index แทน Full Table Scan
  • Composite Index (FirstName, LastName) ช่วยทั้ง COUNT(DISTINCT FirstName) และ COUNT(DISTINCT FirstName, LastName)
  • MySQL ใช้ Loose Index Scan สำหรับ DISTINCT บน Index

เทคนิคเพิ่มเติมสำหรับ COUNT DISTINCT ช้า

วิธีคำอธิบายTrade-off
เพิ่ม INDEXCREATE INDEX idx_col ON table(col)ช่วย SELECT ช้า INSERT/UPDATE
Summary Tableสร้างตารางสรุปไว้ล่วงหน้าต้อง Maintain เอง
APPROX_COUNT_DISTINCTMySQL 8.0.13+ ใช้ HyperLogLogประมาณการ ไม่แม่นยำ 100%
Partitioningแบ่ง Partition ตามคอลัมน์ซับซ้อน ต้องวางแผน

ใช้ APPROX_COUNT_DISTINCT (MySQL 8.0.13+)

SELECT APPROX_COUNT_DISTINCT(FirstName) FROM DemoTable1905;

สรุป: สร้าง INDEX บนคอลัมน์ที่ใช้ COUNT(DISTINCT ...) บ่อย ๆ จะเร่งความเร็วได้มาก สำหรับข้อมูลใหญ่มาก พิจารณา APPROX_COUNT_DISTINCT หรือ Summary Table