2012-01-21 7 views
14

Gần đây tôi gặp vấn đề với một mảng chứa hàng trăm nghìn giá trị và điều duy nhất tôi muốn làm là kiểm tra xem liệu giá trị đã có mặt chưa. Trong trường hợp của tôi, đây là các IP từ nhật ký máy chủ web. Vì vậy, về cơ bản giống như:Có cấu trúc dữ liệu thay thế nào so với mảng trong PHP, nơi tôi có thể hưởng lợi từ các kỹ thuật chỉ mục khác nhau không?

in_array(ip2long(ip),$myarray) đã làm công việc

Tuy nhiên, thời gian tra cứu tăng lên đáng kể và 10k của tra cứu mất khoảng 17 giây hoặc lâu hơn.

Vì vậy, trong trường hợp này tôi không quan tâm liệu tôi có sao chép hay không, tôi chỉ cần kiểm tra sự tồn tại. Vì vậy, tôi có thể lưu trữ các IP trong chỉ mục như thế này:

isset($myarray[ip2long($ip)]) 

Và thời gian tra cứu giảm xuống từ 17 giây (và nhiều hơn nữa) đến thời gian tĩnh 0,8 giây cho tra cứu 10k. Là một giá trị cho mục nhập mảng, tôi chỉ sử dụng int 1.

Tôi nghĩ rằng chỉ mục mảng có thể dựa trên một số b-tree cần có thời gian tra cứu nhật ký (n) và chỉ mục trên băm.

Trong trường hợp của tôi bằng cách sử dụng chỉ mục hoạt động tốt, nhưng có bất kỳ cấu trúc dữ liệu nào mà tôi có thể sử dụng hashmaps như một chỉ mục giá trị, trong đó nhiều giá trị cũng có thể xảy ra (tôi nhận thấy rằng điều này chỉ có ý nghĩa nếu không có quá nhiều bản sao và tôi không thể sử dụng yêu cầu phạm vi/tìm kiếm hiệu quả, đó là lợi ích chính của cấu trúc cây)?

Trả lời

7

Có một loạt các lựa chọn thay thế datastructures ngoài mảng đơn giản trong SPL library kèm với PHP, bao gồm danh sách liên kết, ngăn xếp, đống, hàng đợi vv

Tuy nhiên, tôi nghi ngờ bạn có thể làm cho logic của bạn một toàn bộ rất nhiều hiệu quả hơn nếu bạn flipped mảng của bạn, cho phép bạn thực hiện tra cứu trên khóa (sử dụng chức năng array_key_exists()) thay vì tìm kiếm giá trị. Chỉ mục mảng là một băm, chứ không phải là một btree, làm cho truy cập trực tiếp rất nhanh qua khóa.

Tuy nhiên, nếu bạn đang làm việc với 10 nghìn mục trong một mảng, bạn có thể tận dụng tốt hơn cơ sở dữ liệu, nơi bạn có thể xác định chỉ mục của riêng mình.

+0

Đôi khi giải pháp tốt nằm ngay trước mặt bạn và bạn chỉ nghĩ quá phức tạp. - Tuyệt vời. – Smamatti

+0

Ông lật nó từ những gì tôi hiểu. –

+0

Sử dụng isset ($ a [$ key]) là nhiều (!) Nhanh hơn array_key_exists ($ key, $ a), bởi vì isset là một cấu trúc và array_key_exists() là một hàm. – BurninLeo

1

Mảng có thứ tự tuần tự và nhanh chóng truy cập các phần tử nhất định, vì bạn không cần phải đi qua một cây hoặc làm việc thông qua cấu trúc danh sách tuần tự.

Một tập hợp tất nhiên nhanh hơn ở đây, vì bạn chỉ kiểm tra các phần tử duy nhất chứ không phải tất cả các phần tử (trong mảng).

Cây là tốt cho các cấu trúc được sắp xếp ví dụ. Bạn có thể thực hiện một cây với IP được sắp xếp theo phạm vi của chúng, sau đó bạn có thể quyết định nhanh hơn nếu IP này tồn tại hay không. Tôi không chắc liệu PHP có cung cấp các cấu trúc cây tùy chỉnh như vậy hay không. Tôi đoán bạn sẽ cần phải thực hiện điều này cho mình, nhưng điều này sẽ mất khoảng nửa giờ.

Bạn sẽ tìm thấy mã mẫu trên web cho các cấu trúc cây như vậy.

2

Bạn cũng có tiện ích mở rộng chdb (cơ sở dữ liệu băm liên tục) - điều này hoàn hảo cho việc này.

1

như đã trả lời, bạn có thể sử dụng thương hiệu lớp học mới được cung cấp bởi SPL http://www.php.net/spl

nhưng dường như họ không nhanh như mọi người nghĩ. có lẽ chúng không được thực hiện như chúng ta mong đợi. đó là ý kiến ​​của tôi rằng splfixedarray, ví dụ, không phải là một mảng thật, nhưng một Hashtable là mảng kinh điển php của

NHƯNG cũng có, bạn có một số giải pháp thay thế

đầu tiên bạn có thể lưu trữ kết quả của bạn trong một cơ sở dữ liệu. truy vấn là nhanh vì chỉ số db có thể được tối ưu hóa tốt hơn so với một datastructure php

bạn có thể sử dụng http://www.php.net/sqlite3 và lưu trữ kết quả trong một cơ sở dữ liệu tạm thời (một tập tin hoặc trong bộ nhớ)

Tôi đề nghị một tập tin tạm thời, bởi vì bạn don' t phải tải tất cả trong bộ nhớ và cộng với, bạn có thể thêm từng hàng riêng lẻ (sử dụng http://www.php.net/fgets chẳng hạn)

HTH!

cảm thấy tự do để chỉnh sửa tiếng Anh của tôi