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

จัดเรียง IP Address ให้ถูกต้องด้วย INET_ATON() ใน MySQL


ปัญหา

IP Address เก็บเป็น VARCHAR จัดเรียงแบบ String จะได้ลำดับผิด: 192.168.110.78 192.168.110.87 192.168.110.75 (String Sort: 75, 78, 87 แต่ String จริง: 192.168.110.75, 192.168.110.78, 192.168.110.87)

วิธีแก้: ใช้ INET_ATON()

INET_ATON('192.168.110.75') แปลง IPv4 เป็น Integer (32-bit) จัดเรียงตัวเลขได้ถูกต้อง

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

1. สร้างตาราง

mysql> CREATE TABLE DemoTable (
    -> IpAddress VARCHAR(50)
    -> );
Query OK, 0 rows affected (1.36 sec)

2. เพิ่มข้อมูล

mysql> INSERT INTO DemoTable VALUES('192.168.110.78');
Query OK, 1 row affected (0.18 sec)
mysql> INSERT INTO DemoTable VALUES('192.168.110.87');
Query OK, 1 row affected (0.27 sec)
mysql> INSERT INTO DemoTable VALUES('192.168.110.75');
Query OK, 1 row affected (0.26 sec)

3. จัดเรียงแบบ String (ผิด)

mysql> SELECT * FROM DemoTable ORDER BY IpAddress;

ผลลัพธ์ (String Sort):

+----------------+
| IpAddress      |
+----------------+
| 192.168.110.75 |
| 192.168.110.78 |
| 192.168.110.87 |
+----------------+
3 rows in set (0.00 sec)

ในกรณีนี้ String Sort ตรงกับ Numeric Sort เพราะ Octet ทั้ง 3 ตัวแรกเหมือนกัน แต่ถ้าต่าง Octet จะผิด

4. จัดเรียงด้วย INET_ATON (ถูกต้อง)

mysql> SELECT * FROM DemoTable ORDER BY INET_ATON(IpAddress);

ผลลัพธ์:

+----------------+
| IpAddress      |
+----------------+
| 192.168.110.75 |
| 192.168.110.78 |
| 192.168.110.87 |
+----------------+
3 rows in set (0.00 sec)

ฟังก์ชันคู่: INET_NTOA()

แปลง Integer กลับเป็น IP String

SELECT INET_NTOA(3232236107); -- ผลลัพธ์: 192.168.110.75

ข้อจำกัด

  • รองรับเฉพาะ IPv4 (ไม่รองรับ IPv6)
  • MySQL 5.6.3+ มี INET6_ATON() และ INET6_NTOA() สำหรับ IPv6 (คืนค่า VARBINARY/HEX)
  • คืนค่า NULL หาก IP Format ผิด

Performance & Index

  • ORDER BY INET_ATON(IpAddress) → Filesort (ไม่ใช้ Index บน IpAddress)
  • แก้ไข: สร้าง Generated Column + Index

Generated Column + Index (MySQL 5.7+)

ALTER TABLE DemoTable
ADD COLUMN IpInt INT UNSIGNED 
GENERATED ALWAYS AS (INET_ATON(IpAddress)) STORED,
ADD INDEX idx_ip_int (IpInt);

-- Query เร็วขึ้น ใช้ Index
SELECT * FROM DemoTable ORDER BY IpInt;

กรณีการใช้งานจริง

  • Firewall/Access Log Analysis: จัดเรียง IP เพื่อหาช่วงที่โจมตี
  • GeoIP Lookup: Join กับ IP Range Table (StartIP, EndIP)
  • Network Monitoring: Top Talkers by IP
  • Rate Limiting: นับ Request ต่อ IP