Hãy nhớ rằng IP không phải là một địa chỉ văn bản, mà là một ID số. Tôi gặp trường hợp tương tự (chúng tôi đang thực hiện tra cứu địa chỉ ip) và nếu bạn lưu trữ tất cả địa chỉ IP của mình dưới dạng số nguyên (ví dụ:địa chỉ IP của tôi là 192.115.22.33 nên nó được lưu trữ dưới dạng 3228767777), thì bạn có thể tra cứu IP dễ dàng bằng cách sử dụng các toán tử dịch chuyển bên phải.
Nhược điểm của tất cả các kiểu tra cứu này là bạn không thể hưởng lợi từ các chỉ mục và bạn phải quét toàn bộ bảng bất cứ khi nào bạn thực hiện tra cứu. Lược đồ trên có thể được cải thiện bằng cách lưu trữ cả địa chỉ IP mạng của mạng CIDR (đầu dải) và địa chỉ quảng bá (cuối dải), vì vậy, ví dụ để lưu trữ 192.168.1.0/24, bạn có thể lưu trữ hai cột:
network broadcast
3232235776, 3232236031
Và sau đó, bạn có thể đối sánh nó mà bạn chỉ cần làm
SELECT count(*) FROM bans WHERE 3232235876 >= network AND 3232235876 <= broadcast
Điều này sẽ cho phép bạn lưu trữ mạng CIDR trong cơ sở dữ liệu và khớp chúng với địa chỉ IP một cách nhanh chóng và hiệu quả bằng cách tận dụng các chỉ mục số nhanh.
Lưu ý từ cuộc thảo luận bên dưới :
MySQL 5.0 bao gồm tối ưu hóa truy vấn phạm vi có tên " hợp nhất chỉ mục giao nhau "cho phép tăng tốc các truy vấn như vậy (và tránh quét toàn bộ bảng), miễn là:
- Có một chỉ mục nhiều cột khớp chính xác với các cột trong truy vấn, theo thứ tự. Vì vậy - đối với ví dụ truy vấn ở trên, chỉ mục sẽ cần phải là
(network, broadcast)
. - Tất cả dữ liệu có thể được truy xuất từ chỉ mục. Điều này đúng với
COUNT(*)
, nhưng không đúng vớiSELECT * ... LIMIT 1
.
MySQL 5.6 bao gồm một tối ưu hóa được gọi là MRR cũng sẽ tăng tốc độ truy xuất toàn bộ hàng, nhưng điều đó nằm ngoài phạm vi của câu trả lời này.