2011-07-23 36 views
11

Tôi cần lưu trữ tiềm năng 100 trong số hàng triệu URL trong cơ sở dữ liệu. Mỗi URL phải là duy nhất, do đó tôi sẽ sử dụng ON UPPLINGING DUPLICATE KEY và đếm các URL trùng lặp.Cách lưu trữ URL trong MySQL

Tuy nhiên, tôi không thể tạo chỉ mục trên trường URL vì trường varchar của tôi là 400 ký tự. MySQL đang phàn nàn và nói; "# 1071 - Khóa được chỉ định quá dài; chiều dài khóa tối đa là 767 byte". (Varchar 400 sẽ mất 1200 byte)

Cách tốt nhất để làm điều này là gì, nếu bạn cần xử lý tối thiểu 500.000 URL mỗi ngày trong một máy chủ đơn lẻ?

Chúng tôi đã suy nghĩ bằng cách sử dụng MongoDB cho cùng một ứng dụng, vì vậy chúng tôi chỉ có thể truy vấn MongoDB và tìm URL trùng lặp và cập nhật hàng. Tuy nhiên, tôi không ủng hộ việc giải quyết vấn đề này bằng MongoDB và tôi chỉ muốn sử dụng MySQL ở giai đoạn này vì tôi muốn càng gọn gàng càng tốt trong phần đầu và hoàn thành phần này của dự án nhanh hơn nhiều. (Chúng tôi chưa chơi với MongoDB và không muốn dành thời gian ở giai đoạn này)

Có khả năng nào khác làm điều này bằng cách sử dụng ít tài nguyên và thời gian hơn không. Tôi đã suy nghĩ để có được MD5 băm của URL và lưu trữ nó là tốt. Và tôi có thể biến trường UNIQUE thành thay thế. Tôi biết, sẽ có va chạm nhưng nó là ok để có 5-10-20 bản sao trong 100 triệu URL, nếu đó là vấn đề duy nhất.

Bạn có bất cứ đề xuất nào không? Tôi cũng không muốn dành 10 giây để chèn chỉ một URL, vì nó sẽ xử lý 500 nghìn URL mỗi ngày.

Bạn sẽ đề xuất điều gì?

Chỉnh sửa: Theo yêu cầu, đây là định nghĩa bảng. (Hiện tại tôi không sử dụng MD5, đó là để thử nghiệm)

mysql> DESC url; 
+-------------+-----------------------+------+-----+-------------------+-----------------------------+ 
| Field  | Type     | Null | Key | Default   | Extra      | 
+-------------+-----------------------+------+-----+-------------------+-----------------------------+ 
| url_id  | int(11) unsigned  | NO | PRI | NULL    | auto_increment    | 
| url_text | varchar(400)   | NO |  |     |        | 
| md5   | varchar(32)   | NO | UNI |     |        | 
| insert_date | timestamp    | NO |  | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP | 
| count  | mediumint(9) unsigned | NO |  | 0     |        | 
+-------------+-----------------------+------+-----+-------------------+-----------------------------+ 
5 rows in set (0.00 sec) 
+2

Không có khả năng nhận được 5 xung đột trong 100.000.000 URL cho rằng có 3,4 * 10^38 băm MD5 có thể có ... Và có nhiều băm lớn hơn ở đó. –

+0

Vâng, đúng vậy. Tôi đã không tính toán nó thực sự. – merinn

+0

Vui lòng đăng định nghĩa bảng – Bohemian

Trả lời

8

Theo DNS spec chiều dài tối đa của tên miền là:

DNS tự đặt chỉ có một hạn chế về nhãn đặc biệt
có thể được sử dụng để xác định các hồ sơ tài nguyên. Một hạn chế đó là
liên quan đến độ dài của nhãn và tên đầy đủ. Chiều dài
bất kỳ nhãn nào bị giới hạn trong khoảng từ 1 đến 63 octet. Tên miền đầy đủ
tên được giới hạn ở 255 octet (bao gồm cả dấu tách).

255 * 3 = 765 < 767 (Chỉ cần vừa đủ :-))

Tuy nhiên nhận thấy rằng mỗi thành phần chỉ có thể là 63 ký tự.

Vì vậy, tôi sẽ đề xuất cắt url thành các bit thành phần.

Sử dụng http://foo.example.com/a/really/long/path?with=lots&of=query&parameters=that&goes=on&forever&and=ever

Có lẽ đây sẽ là đủ:

  • giao thức cờ [ "http" -> 0] (cửa hàng "http" như 0, "https" như 1, vv)
  • subdomain [ "foo"] (255-63 = 192 ký tự: tôi có thể trừ đi 2 hơn vì phút tld là 2 ký tự)
  • miền [ "dụ"], (63 ký tự)
  • tld [" com "] (4 nhân vật để xử lý "info" tLD)
  • đường dẫn [ "a/thực sự/dài/path"] (miễn là bạn muốn - cửa hàng trong một bảng riêng biệt)
  • queryparameters [ "with = lots & of = truy vấn & thông số = rằng & đi = trên & mãi mãi & và = bao giờ"] (cửa hàng trong một bảng chìa khóa/giá trị riêng biệt)
  • PortNumber/chứng thực thứ mà hiếm khi được sử dụng có thể trong một bảng có khóa riêng biệt nếu thực sự cần thiết.

này cung cấp cho bạn một số lợi thế đẹp:

  • Chỉ số này chỉ có trên các bộ phận của url mà bạn cần phải tìm kiếm trên
  • truy vấn có thể được giới hạn ở những khác nhau (chỉ số nhỏ hơn!) các phần url (tìm mọi url trong miền facebook chẳng hạn)
  • bất kỳ url nào có tên miền/miền phụ quá dài là không có thật
  • dễ dàng loại bỏ tham số truy vấn.
  • dễ làm trường hợp không phân biệt tên miền/tìm kiếm tld
  • hủy đường cú pháp (": //" sau giao thức "." Giữa tên miền phụ/tên miền, tên miền/tld, "/" giữa tld và đường dẫn " ? "trước truy vấn", & "" = "trong truy vấn)
  • Tránh vấn đề bảng thưa thớt lớn. Hầu hết các url sẽ không có tham số truy vấn hoặc đường dẫn dài. Nếu các trường này nằm trong một bảng riêng biệt thì bảng chính của bạn sẽ không lấy kích thước. Khi thực hiện truy vấn, nhiều bản ghi sẽ phù hợp với bộ nhớ, do đó hiệu suất truy vấn nhanh hơn.
  • (nhiều lợi thế hơn tại đây).
+0

+1 cho 765 <767: P –

+0

cảm ơn +1 .. bất kể lý do gì :-P – Pat

+1

Lưu ý rằng '4 ký tự' để xử lý TLD không phải là cách thực hành tốt. Từ http://stackoverflow.com/questions/9238640/how-long-can-a-tld-possibly-be có thể lên đến 63 ký tự, lớn nhất hiện tại là 24. – Eborbob

-1

Bạn có thể thay đổi url_text từ VarChar (400) thành văn bản, sau đó bạn có thể thêm chỉ mục văn bản đầy đủ vào nó cho phép bạn tìm kiếm sự tồn tại của URL trước khi bạn chèn nó.

+0

Chỉ mục văn bản đầy đủ cho URL? – Karolis

+0

Một số URL có thể dài tối đa 2083 ký tự, ví dụ: IE8. Trong URL thực hành bình thường sẽ không được lâu nhưng bạn nên chuẩn bị cho chúng. Xem thảo luận http://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url – woot586

+0

Ý tôi là không phải là độ dài của URL, nhưng tính hữu ích của chỉ mục toàn văn cho các URL :) – Karolis

0

Để lập chỉ mục trường có tối đa 767 ký tự, bộ ký tự phải là ascii hoặc tương tự, nó không thể utf8 vì nó sử dụng 3 byte trên mỗi char, vì vậy maximun rộng cho các trường utf-8 được lập chỉ mục là 255

Tất nhiên, một trường 776 ascii url, xuất siêu 400 ký tự đầu tiên của bạn. Tất nhiên, một số url đã vượt qua giới hạn 767. Có lẽ bạn có thể lưu trữ và lập chỉ mục trên 735 ký tự đầu tiên cộng với hàm băm md5. Bạn cũng có thể có trường văn bản full_url để giữ nguyên giá trị ban đầu.
Lưu ý rằng bộ mã ascii đủ tốt cho các url

+0

xem phương pháp thay thế tốt [ở đây] (http://stackoverflow.com/questions/5147867/best-way-to-store-url-in-mysql-for-a-readwrite-intensive-application/5148006#5148006) đăng bởi @razzed –

0

URL được tạo đúng chỉ có thể chứa các ký tự trong phạm vi ASCII - các ký tự khác cần phải được mã hóa. Vì vậy, giả sử URL bạn dự định lưu trữ được định dạng tốt (và nếu không, bạn có thể sửa chúng trước khi chèn chúng vào cơ sở dữ liệu), bạn có thể xác định ký tự cột url_text của bạn thành ASCII (latin1 trong MySQL). Với ASCII, một char là một byte, và bạn sẽ có thể lập chỉ mục toàn bộ 400 ký tự như bạn muốn.

0

Các tỷ lệ cược của một vụ va chạm giả mạo với MD5 (128 bit) có thể được phrased theo cách này:

"Nếu bạn có 9 nghìn tỷ mặt hàng khác nhau, chỉ có một cơ hội trong 9 nghìn tỷ mà hai trong số họ có cùng MD5. "

Để cụm từ theo cách khác, nó có nhiều khả năng bị ảnh hưởng bởi thiên thạch trong khi giành chiến thắng trong cuộc xổ số lớn.

+0

Tôi tự hỏi nếu nó là, thực sự ... Tôi gần như bị cám dỗ để đi làm toán ... – Ben

+0

Tôi nghĩ rằng đó là không chính xác: http://en.wikipedia.org/wiki/Birthday_problem# Cast_as_a_collision_problem – endolith

Các vấn đề liên quan