Hãy nhớ rằng IP không phải là một địa chỉ văn bản, nhưng một ID số. Tôi có tình huống tương tự (chúng tôi đang thực hiện tra cứu địa lý-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 do đó nó được lưu trữ dưới dạng 3228767777), thì bạn có thể tra cứu địa chỉ IP dễ dàng bằng cách sử dụng toán tử dịch chuyển phải.
Nhược điểm của tất cả các loại tra cứu này là bạn không thể hưởng lợi từ chỉ mục và bạn phải thực hiện quét toàn bộ bảng bất cứ khi nào bạn tra cứu. Đề án 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ãy) và địa chỉ quảng bá (phần cuối của 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ể để phù hợp với nó, bạn chỉ cần làm
SELECT count(*) FROM bans WHERE 3232235876 >= network AND 3232235876 <= broadcast
này sẽ cho phép bạn lưu trữ mạng CIDR trong cơ sở dữ liệu và kết hợp chúng chống lại các địa chỉ IP một cách nhanh chóng và hiệu quả bằng cách tận dụng nhanh chóng chỉ số dạng số.
Lưu ý từ cuộc thảo luận dưới đây:
MySQL 5.0 bao gồm một tối ưu hóa truy vấn dao động gọi là "index merge intersect" cho phép để tăng tốc độ truy vấn như vậy (và tránh quét bảng đầy đủ), 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 đối với SELECT * ... LIMIT 1
.
MySQL 5.6 bao gồm tối ưu hóa được gọi là MRR cũng sẽ tăng tốc độ truy xuất hàng đầy đủ, nhưng điều đó nằm ngoài phạm vi của câu trả lời này.
raspi, tôi biết câu hỏi này cũ, nhưng ... là cột cidr của bạn số bit trong mặt nạ mạng, vì vậy ipv6 luôn 64 và ipv4 là số từ 0 và 32? Mặc dù tôi cho rằng 0 sẽ cấm tất cả các địa chỉ ... :) – ErikE