MySQL có thể thực hiện hợp lý các truy vấn trên hàng tỷ hàng không?


283

Tôi đang lên kế hoạch lưu trữ các bản quét từ máy quang phổ khối trong cơ sở dữ liệu MySQL và muốn biết liệu việc lưu trữ và phân tích lượng dữ liệu này có khả thi từ xa hay không. Tôi biết hiệu suất thay đổi tùy theo môi trường, nhưng tôi đang tìm kiếm thứ tự độ lớn: các truy vấn sẽ mất 5 ngày hay 5 mili giây?

định dạng đầu vào

Mỗi tệp đầu vào chứa một lần chạy của máy quang phổ; mỗi lần chạy bao gồm một tập hợp các lần quét và mỗi lần quét có một mảng dữ liệu theo thứ tự. Có một chút siêu dữ liệu, nhưng phần lớn tệp bao gồm các mảng ints 32 hoặc 64 bit hoặc float.

Hệ thống máy chủ

| ---------------- + ------------------------------- |
| HĐH | Windows 2008 64-bit |
| Phiên bản MySQL | 5.5.24 (x86_64) |
| CPU | 2x Xeon E5420 (tổng cộng 8 lõi) |
| RAM | 8GB |
| Hệ thống tập tin SSD | 500 GiB |
| RAID RAID | 12 TiB |
| ---------------- + ------------------------------- |

Có một số dịch vụ khác đang chạy trên máy chủ sử dụng thời gian xử lý không đáng kể.

Thống kê tập tin

| ------------------ + -------------- |
| số lượng tập tin | ~ 16.000 |
| tổng kích thước | 1,3 TiB |
| kích thước tối thiểu | 0 byte |
| kích thước tối đa | 12 GiB |
| nghĩa là | 800 MiB |
| trung vị | 500 MiB |
| tổng số điểm dữ liệu | ~ 200 tỷ |
| ------------------ + -------------- |

Tổng số datapoint là một ước tính rất sơ bộ.

Lược đồ đề xuất

Tôi đang lên kế hoạch thực hiện những điều "đúng" (nghĩa là bình thường hóa dữ liệu như điên) và vì vậy sẽ có một runsbảng, một spectrabảng có khóa ngoại runsvà một datapointsbảng có khóa ngoại spectra.

Câu hỏi datapoint 200 tỷ

Tôi sẽ phân tích trên nhiều quang phổ và thậm chí nhiều lần chạy, dẫn đến các truy vấn có thể chạm vào hàng triệu hàng. Giả sử tôi lập chỉ mục mọi thứ một cách chính xác (đó là một chủ đề cho một câu hỏi khác) và không cố gắng xáo trộn hàng trăm MiB trên mạng, liệu MySQL có thể xử lý vấn đề này từ xa không?

thông tin bổ sung

Dữ liệu quét sẽ đến từ các tệp ở định dạng mzML dựa trên XML . Thịt của định dạng này là trong các <binaryDataArrayList>yếu tố nơi dữ liệu được lưu trữ. Mỗi lần quét tạo ra> = 2 <binaryDataArray>phần tử, được ghép lại với nhau, tạo thành một mảng 2 chiều (hoặc nhiều hơn) của biểu mẫu [[123.456, 234.567, ...], ...].

Những dữ liệu này là ghi một lần, vì vậy cập nhật hiệu suất và an toàn giao dịch không phải là mối quan tâm.

Kế hoạch ngây thơ của tôi cho một lược đồ cơ sở dữ liệu là:

runs bàn

| tên cột | loại |
| ------------- + ------------- |
| id | KHÓA CHÍNH |
| bắt đầu | THỜI GIAN |
| tên | VARCHAR |
| ------------- + ------------- |

spectra bàn

| tên cột | loại |
| ---------------- + ------------- |
| id | KHÓA CHÍNH |
| tên | VARCHAR |
| chỉ số | INT |
| phổ_type | INT |
| đại diện | INT |
| run_id | KHOẢN NGOẠI TỆ |
| ---------------- + ------------- |

datapoints bàn

| tên cột | loại |
| ------------- + ------------- |
| id | KHÓA CHÍNH |
| phổ_id | KHOẢN NGOẠI TỆ |
| mz | NHÂN ĐÔI |
| số lượng | NHÂN ĐÔI |
| chỉ số | INT |
| ------------- + ------------- |

Điều này có hợp lý không?


Vì vậy, như bạn có thể đã suy luận, tôi là lập trình viên, không phải nhà sinh vật học trong phòng thí nghiệm, vì vậy tôi không biết về khoa học cũng như các nhà khoa học thực tế.

Đây là một âm mưu của một phổ (quét) loại dữ liệu mà tôi sẽ xử lý:

Ảnh chụp màn hình người xem

Mục tiêu của phần mềm là tìm ra vị trí và mức độ quan trọng của các đỉnh. Chúng tôi sử dụng gói phần mềm độc quyền để tìm ra điều này ngay bây giờ, nhưng chúng tôi muốn viết chương trình phân tích của riêng mình (bằng R) để chúng tôi biết cái quái gì đang diễn ra dưới tờ. Như bạn có thể thấy, phần lớn dữ liệu không thú vị, nhưng chúng tôi không muốn loại bỏ dữ liệu hữu ích mà thuật toán của chúng tôi đã bỏ lỡ. Khi chúng tôi có một danh sách các đỉnh có thể xảy ra mà chúng tôi hài lòng, phần còn lại của đường ống sẽ sử dụng danh sách đỉnh đó thay vì danh sách dữ liệu thô. Tôi cho rằng sẽ đủ để lưu trữ các điểm dữ liệu thô dưới dạng một đốm lớn, vì vậy chúng có thể được phân tích lại nếu cần, nhưng chỉ giữ các đỉnh như các mục cơ sở dữ liệu riêng biệt. Trong trường hợp đó, sẽ chỉ có vài chục đỉnh trên mỗi phổ, vì vậy các công cụ chia tỷ lệ điên rồ không nên '



8
Vì đây là dữ liệu phổ kế khối lượng bỏ phiếu A / D thô, nên có vẻ thực sự ngu ngốc khi lưu trữ nó trong cơ sở dữ liệu. Tôi sẽ lấy dữ liệu thô của mình, kết xuất nó, xử lý nó và lưu trữ KẾT QUẢ đã xử lý trong cơ sở dữ liệu. Các kết quả sẽ là (a) dạng sóng được lưu trữ một dạng sóng trên mỗi hàng, (b) dữ liệu khác được liên kết với các dạng sóng như đường cong hiệu chuẩn và (c) các hàng kết quả trong cơ sở dữ liệu. Điều này sẽ cắt hàng tỷ hàng nở từ thiết kế của bạn. Khi bạn muốn chạy lại một phân tích ban đầu, bạn sẽ thực sự chỉnh sửa một số tham số, chạy một hoạt động tính toán khổng lồ và lưu trữ các kết quả mới trong db.
Warren P

Câu trả lời:


115

Tôi không quen thuộc lắm với nhu cầu của bạn, nhưng có lẽ việc lưu trữ từng điểm dữ liệu trong cơ sở dữ liệu là một chút quá mức cần thiết. Nghe có vẻ giống như cách tiếp cận lưu trữ thư viện hình ảnh bằng cách lưu trữ từng pixel dưới dạng một bản ghi riêng trong cơ sở dữ liệu quan hệ.

Theo nguyên tắc chung, hầu hết thời gian lưu trữ dữ liệu nhị phân trong cơ sở dữ liệu. Thường có một cách tốt hơn để giải quyết vấn đề. Mặc dù việc lưu trữ dữ liệu nhị phân trong cơ sở dữ liệu quan hệ không phải là sai, nhưng thường thì những bất lợi vượt trội hơn nhiều so với mức tăng. Cơ sở dữ liệu quan hệ, như tên gọi ám chỉ, phù hợp nhất để lưu trữ dữ liệu quan hệ. Dữ liệu nhị phân không quan hệ. Nó thêm kích thước (thường là đáng kể) vào cơ sở dữ liệu, có thể ảnh hưởng đến hiệu suất và có thể dẫn đến các câu hỏi về việc duy trì các phiên bản MySQL kỷ lục. Tin tốt là có những cơ sở dữ liệu đặc biệt phù hợp để lưu trữ dữ liệu nhị phân. Một trong số đó, trong khi không phải lúc nào cũng dễ thấy, là hệ thống tệp của bạn! Chỉ cần đưa ra một cấu trúc đặt tên thư mục và tệp cho các tệp nhị phân của bạn,

Một cách tiếp cận khác là sử dụng hệ thống lưu trữ dựa trên tài liệu cho dữ liệu của bạn (và có lẽ là phổ) và sử dụng MySQL cho các lần chạy (hoặc có thể đặt các lần chạy vào cùng DB như các dữ liệu khác).


5
Tại sao nó được coi là sai khi lưu trữ dữ liệu nhị phân trong cơ sở dữ liệu? (Hỏi một phần vì tôi tò mò nhưng cũng vì tôi có thể nghĩ ra trường hợp sử dụng cho nó.)

15
Nếu dữ liệu nhị phân không có giá trị riêng lẻ thì không nên lưu trữ dưới dạng một hàng duy nhất. Pixel 500x325 trên một hình ảnh là không liên quan.

1
Đó là một điểm rất tốt. Có lẽ chúng ta nên giữ các tệp thô xung quanh trong trường hợp chúng ta cần phải lấy lại các thứ sau đó, nhưng sự tương tự để lưu trữ hình ảnh là một điều tuyệt vời. Chúng tôi sẽ không cần truy cập vào từng datapoint bao giờ (trừ khi chúng tôi đang thực hiện lại trích xuất cực đại), vì vậy chỉ cần lưu trữ thông tin thống kê được trích xuất sẽ tốt hơn nhiều.
haxney

107

Tôi đã từng làm việc với một cơ sở dữ liệu MySQL rất lớn (Terabyte +). Chiếc bàn lớn nhất mà chúng tôi có có nghĩa là hơn một tỷ hàng. Đây là sử dụng MySQL 5.0, vì vậy có thể mọi thứ đã được cải thiện.

Nó đã làm việc. MySQL xử lý dữ liệu chính xác hầu hết thời gian. Nó là vô cùng khó sử dụng mặc dù. (Nếu bạn muốn có sẵn sáu cấp độ sigma với một terabyte dữ liệu, đừng sử dụng MySQL. Chúng tôi là một công ty khởi nghiệp không có DBA và quỹ hạn chế.)

Chỉ cần sao lưu và lưu trữ dữ liệu là một thách thức. Sẽ mất nhiều ngày để khôi phục lại bảng nếu chúng ta cần.

Chúng tôi đã có nhiều bảng trong phạm vi 10-100 triệu hàng. Bất kỳ tham gia quan trọng nào vào các bảng đều quá tốn thời gian và sẽ mất mãi mãi. Vì vậy, chúng tôi đã viết các thủ tục được lưu trữ để 'đi bộ' các bảng và xử lý tham gia vào phạm vi của 'id'. Theo cách này, chúng tôi sẽ xử lý dữ liệu 10-100.000 hàng cùng một lúc (Tham gia với id 1-100.000 sau đó là 100.001-200.000, v.v.). Điều này nhanh hơn đáng kể so với tham gia vào toàn bộ bảng.

Sử dụng các chỉ mục trên các bảng rất lớn không dựa trên khóa chính cũng khó khăn hơn nhiều. Mysql 5.0 lưu trữ các chỉ mục thành hai phần - nó lưu các chỉ mục (trừ chỉ mục chính) dưới dạng chỉ mục cho các giá trị khóa chính. Vì vậy, việc tra cứu được lập chỉ mục được thực hiện thành hai phần: MySQL đầu tiên đi đến một chỉ mục và lấy từ đó các giá trị khóa chính mà nó cần tìm, sau đó nó tìm kiếm thứ hai trên chỉ mục khóa chính để tìm vị trí của các giá trị đó.

Mạng lưới của điều này là đối với các bảng rất lớn (1-200 triệu cộng với hàng) việc lập chỉ mục theo bảng sẽ hạn chế hơn. Bạn cần ít hơn, chỉ mục đơn giản hơn. Và thực hiện ngay cả các câu lệnh chọn đơn giản không trực tiếp trên một chỉ mục có thể không bao giờ quay trở lại. Trường hợp mệnh đề phải đạt chỉ số hoặc quên nó.

Nhưng tất cả những gì đang được nói, mọi thứ đã thực sự hoạt động. Chúng tôi đã có thể sử dụng MySQL với các bảng rất lớn này và thực hiện các phép tính và nhận câu trả lời đúng.

Cố gắng phân tích trên 200 tỷ hàng dữ liệu sẽ đòi hỏi phần cứng rất cao cấp và rất nhiều sự nắm giữ và kiên nhẫn. Chỉ cần giữ dữ liệu được sao lưu ở định dạng mà bạn có thể khôi phục sẽ là một công việc quan trọng.

Tôi đồng ý với câu trả lời của srini.venigalla rằng bình thường hóa dữ liệu như điên có thể không phải là một ý tưởng hay ở đây. Việc tham gia trên nhiều bảng với nhiều dữ liệu đó sẽ mở ra cho bạn nguy cơ sắp xếp tệp có thể có nghĩa là một số truy vấn của bạn sẽ không bao giờ quay trở lại. Khử nhiễu bằng các khóa số nguyên, đơn giản sẽ cho bạn cơ hội thành công cao hơn.

Tất cả mọi thứ chúng tôi có là InnoDB. Về MyISAM so với InnoDB: Điều chính sẽ là không kết hợp cả hai. Bạn thực sự không thể tối ưu hóa máy chủ cho cả hai vì cách MySQL lưu trữ khóa và dữ liệu khác. Chọn một hoặc một cho tất cả các bảng trong một máy chủ nếu bạn có thể. MyISAM có thể giúp đỡ với một số vấn đề về tốc độ, nhưng nó có thể không giúp ích gì cho công việc DBA tổng thể cần phải thực hiện - có thể là một kẻ giết người.


1
MySQL đã cải thiện rất nhiều trong bộ phận chỉ mục (...) kể từ 5.0. Sẽ rất thú vị khi xem cách nó hành xử bây giờ.
Đổ chuông

70

bình thường hóa dữ liệu như điên

Bình thường hóa dữ liệu như điên có thể không phải là chiến lược đúng đắn trong trường hợp này. Giữ các tùy chọn của bạn mở bằng cách lưu trữ dữ liệu cả ở dạng Chuẩn hóa và cả ở dạng xem cụ thể hóa rất phù hợp với ứng dụng của bạn. Điều quan trọng trong loại ứng dụng này là KHÔNG viết các truy vấn adhoc. Mô hình truy vấn quan trọng hơn mô hình dữ liệu. Bắt đầu với các truy vấn mục tiêu của bạn và hướng tới mô hình dữ liệu tối ưu.

Is this reasonable?

Tôi cũng sẽ tạo một bảng phẳng bổ sung với tất cả dữ liệu.

run_id | spectrum_id | data_id | <data table columns..> |

Tôi sẽ sử dụng bảng này làm nguồn chính của tất cả các truy vấn. Lý do là để tránh phải tham gia bất kỳ. Tham gia mà không lập chỉ mục sẽ làm cho hệ thống của bạn rất không sử dụng được và việc có các chỉ mục trên các tệp khổng lồ như vậy sẽ khủng khiếp không kém.

Chiến lược là, trước tiên hãy truy vấn bảng trên, kết quả các kết quả vào bảng tạm thời và tham gia bảng tạm thời với các bảng tra cứu của Run và Spectrum và lấy dữ liệu bạn muốn.


Bạn đã phân tích nhu cầu Viết của bạn so với nhu cầu Đọc chưa? Sẽ rất hấp dẫn khi bỏ SQL và đi đến các cơ chế lưu trữ dữ liệu không chuẩn. Theo quan điểm của tôi, nó nên là phương sách cuối cùng.

Để tăng tốc độ ghi, bạn có thể muốn thử phương thức Handler Socket. Percona, nếu tôi nhớ, gói Handler Socket trong gói cài đặt của họ. (không liên quan đến Percona!)

http://yoshinorimatsunobu.blogspot.com/2010/10/USE-mysql-as-nosql-story-for.html


33

Câu trả lời ngắn gọn là có đủ điều kiện - vì số lượng hàng phát triển lược đồ, kiểu dữ liệu và thao tác chính xác mà bạn chọn tăng lên về mức độ quan trọng.

Bao nhiêu bạn bình thường hóa dữ liệu của bạn phụ thuộc vào các hoạt động bạn dự định thực hiện trên dữ liệu được lưu trữ. Bảng 'datapoints của bạn nói riêng có vẻ có vấn đề - bạn có định so sánh điểm thứ n từ bất kỳ quang phổ cụ thể nào với mth của bất kỳ điểm nào khác không? Nếu không, lưu trữ chúng riêng biệt có thể là một sai lầm. Nếu các điểm dữ liệu của bạn không đứng một mình mà chỉ có ý nghĩa trong bối cảnh phổ liên kết của chúng, bạn không cần một khóa CHÍNH - một khóa ngoại cho quang phổ và cột 'nth' (cột 'chỉ mục' của bạn?) Sẽ đủ .

Xác định các hoạt động giữa và phổ trong bạn phải thực hiện và sau đó tìm ra cách rẻ nhất để thực hiện chúng. Nếu sự bình đẳng là tất cả những gì cần thiết thì chúng có thể không được chuẩn hóa - có thể với một số siêu dữ liệu thống kê được tính toán trước hỗ trợ các hoạt động của bạn. Nếu bạn thực sự cần truy cập in-SQL vào các điểm dữ liệu riêng lẻ, đảm bảo bạn giảm kích thước của mỗi hàng xuống số lượng trường tối thiểu trần và kiểu dữ liệu nhỏ nhất có thể.

MySQL lớn nhất tôi từng quản lý cá nhân là ~ 100 triệu hàng. Ở kích thước này, bạn muốn giữ các hàng của mình và do đó các trường của bạn có kích thước cố định - điều này cho phép MySQL tính toán hiệu quả vị trí của bất kỳ hàng nào trong bảng bằng cách nhân số lần kích thước cố định của mỗi hàng (nghĩ về số học con trỏ) - mặc dù chi tiết chính xác phụ thuộc vào công cụ lưu trữ mà bạn dự định sử dụng. Sử dụng MyISAM nếu bạn có thể thoát khỏi nó, cái mà nó thiếu độ tin cậy thì nó bù lại về tốc độ, và trong tình huống của bạn thì nó cũng đủ. Thay thế các trường có kích thước biến như VARCHAR bằng CHAR (n) và sử dụng RTRIM () cho các truy vấn đọc của bạn.

Khi các hàng trong bảng của bạn có chiều rộng cố định, bạn có thể giảm số byte bằng cách đánh giá cẩn thận các kiểu dữ liệu số nguyên của MySQL (một số trong số đó không phải là tiêu chuẩn). Mỗi khoản tiết kiệm 1 byte bạn có thể thực hiện bằng cách chuyển đổi INT 4 byte thành MEDIUMINT 3 byte giúp bạn tiết kiệm ~ 1MB trên một triệu hàng - nghĩa là I / O ít đĩa hơn và bộ nhớ đệm hiệu quả hơn. Sử dụng các kiểu dữ liệu nhỏ nhất có thể mà bạn có thể thoát khỏi . Đánh giá cẩn thận các loại dấu phẩy động và xem liệu bạn có thể thay thế NHÂN ĐÔI 8 byte bằng FLOAT 4 byte hoặc thậm chí <8 byte điểm cố định . Chạy thử nghiệm để đảm bảo rằng bất cứ điều gì bạn chọn không cắn bạn sau này.

Tùy thuộc vào các thuộc tính dự kiến ​​của tập dữ liệu của bạn và các thao tác được yêu cầu, có thể tiết kiệm thêm cho các mã hóa khác thường của các giá trị của bạn (các mẫu / lặp lại dự kiến ​​có thể được mã hóa thành một chỉ mục thành một tập hợp các giá trị, dữ liệu thô chỉ có thể đóng góp một cách có ý nghĩa siêu dữ liệu và bị loại bỏ, v.v.) - mặc dù các tối ưu hóa kỳ lạ, không trực quan, mang tính hủy diệt chỉ đáng giá khi mọi tùy chọn khác đã được thử.

Quan trọng nhất, cho dù cuối cùng bạn làm gì, đừng cho rằng bạn đã chọn lược đồ hoàn hảo và sau đó mù quáng bắt đầu bán 10 triệu hàng triệu hồ sơ. Thiết kế tốt cần có thời gian để phát triển. Tạo một bộ dữ liệu thử nghiệm lớn nhưng có thể quản lý (giả sử, 1-5%) và xác minh tính chính xác và hiệu suất của lược đồ của bạn. Xem cách các hoạt động khác nhau thực hiện (http://dev.mysql.com/doc/refman/5.0/en/USE-explain.html) và đảm bảo rằng bạn cân bằng lược đồ của mình để ưu tiên các hoạt động thường xuyên nhất.

Tôi đã nói ngắn? Rất tiếc. Dù sao, chúc may mắn!


23

Dường như lý do duy nhất để loại bỏ dữ liệu điểm dữ liệu ra khỏi XML (trái ngược với siêu dữ liệu như thời gian và kiểu chạy) và vào một dạng cơ sở dữ liệu là khi bạn đang phân tích phổ qua các mảng - có lẽ là tìm thấy tất cả chạy với một chữ ký nhất định. Chỉ có bạn biết miền vấn đề của bạn ngay bây giờ, nhưng điều này có thể giống với việc lưu trữ nhạc được lấy mẫu ở 96kHz với 1 mẫu mỗi hàng. Tôi không chắc chắn kích thước là vấn đề nhiều hơn cách sử dụng dữ liệu. Truy vấn trên dữ liệu sẽ tương đương với việc yêu cầu biên độ tương đối 2 phút vào bài hát trên tất cả các bài hát của The Beatles. Nếu bạn biết loại phân tích có thể được thực hiện, thì hoàn toàn có thể thực hiện những phân tích này trên các tín hiệu và lưu trữ những phân tích trong siêu dữ liệu về hoạt động có thể có ý nghĩa hơn.

Tôi cũng không chắc liệu dữ liệu nguồn của bạn có thưa thớt không. Hoàn toàn có thể là một phổ trong cơ sở dữ liệu chỉ nên bao gồm các mục nhập khác không trong khi XML gốc không bao gồm các mục nhập bằng 0 và do đó tổng số hàng của bạn có thể ít hơn nhiều so với dữ liệu nguồn.

Vì vậy, giống như nhiều câu hỏi, trước khi hỏi về việc MySQL xử lý mô hình của bạn, lùi lại và xem mô hình và cách sử dụng nó có lẽ phù hợp hơn là lo lắng về hiệu suất.


Sau khi xem xét các cập nhật câu hỏi của bạn, tôi nghĩ rằng một mô hình trong đó dữ liệu nhị phân được lưu trữ dưới dạng BLOB hoặc chỉ một con trỏ tới tệp là đủ và sửa đổi mô hình của bạn để lưu trữ dữ liệu về các đỉnh quan trọng đã được xác định khi dữ liệu là lần đầu tiên đọc.


18

Tôi điều hành một dịch vụ phân tích trang web với khoảng 50 máy chủ cơ sở dữ liệu, mỗi máy chủ chứa nhiều bảng hơn 100 triệu hàng và một số có xu hướng hơn một tỷ hàng, đôi khi lên tới hai tỷ (trên mỗi máy chủ).

Hiệu suất ở đây là tốt. Nó là dữ liệu rất bình thường. Tuy nhiên - mối quan tâm chính của tôi khi đọc điều này là bạn sẽ vượt qua mốc 4.2 tỷ hàng cho các bảng này (có thể không "chạy" nhưng có thể là hai bảng khác), có nghĩa là bạn sẽ cần sử dụng BIGINT thay vì INT cho các khóa chính / khóa ngoài.

Hiệu suất của MySQL với các trường BIGINT trong một cột được lập chỉ mục thật kinh khủng so với INT. Tôi đã phạm sai lầm khi làm điều này một lần với một cái bàn mà tôi nghĩ có thể tăng lên trên kích thước này, và một khi nó đạt được vài trăm triệu hàng thì hiệu suất chỉ đơn giản là rất tệ. Tôi không có số liệu thô nhưng khi tôi nói xấu, ý tôi là Windows ME tệ.

Cột này là khóa chính. Chúng tôi đã chuyển đổi nó trở lại chỉ là một INTico và uy tín, hiệu suất đã tốt trở lại.

Tất cả các máy chủ của chúng tôi tại thời điểm đó đều có trên Debian 5 và với MySQL 5.0. Chúng tôi đã nâng cấp lên Debian 6 và Percona MySQL 5.5, vì vậy mọi thứ có thể đã được cải thiện kể từ đó. Nhưng dựa trên kinh nghiệm của tôi ở đây, không, tôi không nghĩ nó sẽ hoạt động tốt.


17

Cho dù nó có hoạt động hay không, bạn sẽ luôn gặp phải cùng một vấn đề với một phương tiện lưu trữ nguyên khối duy nhất: các đĩa bị chậm. Với tốc độ 100 MB / s (khá tốt cho phương tiện kéo sợi), phải mất 3 giờ chỉ để đọc bảng 1TB; giả sử không có phân tích hoặc tìm kiếm hoặc sự chậm trễ khác làm bạn chậm lại.

Đây là lý do tại sao gần như mọi cài đặt "dữ liệu lớn" sử dụng một số loại lưu trữ dữ liệu phân tán. Bạn có thể chi gấp 8 lần số tiền để xây dựng một máy tính siêu tuyệt vời để chạy DB của mình, nhưng nếu bạn có nhiều dữ liệu có thể được quét song song, bạn hầu như luôn luôn phân phối tải trên 8 máy tính rẻ hơn.

Các dự án như hadoop được xây dựng đặc biệt cho các mục đích như thế này. Bạn xây dựng một cụm gồm cả đống máy tính rẻ tiền, phân phối dữ liệu trên tất cả chúng và truy vấn chúng song song. Đó chỉ là một trong nửa tá giải pháp được xây dựng xung quanh cùng một ý tưởng, nhưng nó là một giải pháp rất phổ biến.


13

Hừm ... Tôi thấy oly hai lý do tại sao bạn chọn loại cấu trúc dữ liệu này:

  • bạn thực sự cần phải thực hiện bất kỳ datapoint so với bất kỳ truy vấn datapoint nào
  • bạn dự định thực hiện tất cả logic của bạn trong SQL

Bây giờ, tôi sẽ đề nghị xem xét kỹ các yêu cầu của bạn và xác minh rằng ít nhất một trong những giả định trên là đúng. Nếu không phải là sự thật, bạn chỉ đang làm mọi thứ chậm hơn. Đối với loại dữ liệu này, trước tiên tôi sẽ đề nghị tìm hiểu cách dữ liệu được dự kiến ​​sẽ được truy cập, loại chính xác nào bạn sẽ cần, v.v. - và sau đó thiết kế cơ sở dữ liệu của bạn xung quanh những dữ liệu đó.

PS: Hãy nhớ rằng bạn sẽ cần ít nhất 36 + 5 byte cho mỗi điểm dữ liệu, vì vậy với các điểm dữ liệu 200B sẽ cung cấp cho bạn ít nhất 8.2 TB không gian cần thiết.

PPS: Bạn không cần idcột trong datapointsbảng, PRIMARY KEY (spectrum_id, index)có lẽ là đủ (chỉ cần cẩn thận indexcó thể là một từ dành riêng)


12

BIÊN TẬP:

ĐỪNG LÀM ĐIỀU NÀY TRONG MYSQL VỚI DỮ LIỆU LƯU TRỮ TRÊN MỘT DISK. Chỉ cần đọc lượng dữ liệu đó từ một phương tiện duy nhất sẽ mất hàng giờ. Bạn cần phải QUY MÔ, KHÔNG LÊN.

Và bạn cần phải chuẩn hóa dữ liệu của mình nếu bạn muốn phân tích dữ liệu hiệu quả. Bạn không thiết kế một hệ thống trực tuyến ở đây. Bạn muốn crunch số, thiết kế cho phù hợp.

Câu trả lời gốc dưới đây.


Câu trả lời sẽ thay đổi tùy thuộc vào truy vấn của bạn, MySQL có thể không phải là công cụ tốt nhất cho công việc này. Bạn có thể muốn xem xét giải pháp mà bạn có thể mở rộng "ra" chứ không phải "lên". Nếu bạn sẵn sàng bỏ ra một số nỗ lực, có lẽ bạn nên tìm kiếm một giải pháp Bản đồ thu nhỏ như Hadoop.

Nếu bạn muốn thực hiện nhiều truy vấn đặc biệt hơn , giải pháp BigQuery của Google có thể phù hợp với bạn. Bài thuyết trình có liên quan từ Google I / O 2012: Crunching Big Data with BigQuery

Vì vậy, giải pháp sẽ phụ thuộc vào việc đây có phải là một lần hay không và nếu bạn muốn hỗ trợ hợp lý các truy vấn ad hoc.


9

Không ai đã đề cập, do đó đề nghị của tôi. Hãy nhìn vào các giải pháp MySQL ồ ạt . Ví dụ, xem bài trình bày tumblr được đánh giá cao này .

Khái niệm này là:

  • Thay vì một cơ sở dữ liệu lớn thêm
  • Sử dụng nhiều cái nhỏ giữ các phần của dữ liệu gốc

Do đó, bạn có thể mở rộng theo chiều ngang, thay vì cố gắng cải thiện hiệu suất dọc. BigTableGFS của Google cũng đang sử dụng các nút có thể mở rộng theo chiều ngang giá rẻ để lưu trữ và truy vấn petabyte dữ liệu.

Tuy nhiên, sẽ có rắc rối nếu bạn cần chạy truy vấn trên các phân đoạn khác nhau.


Nếu bất cứ ai quan tâm, tôi đã tạo ra một ứng dụng shending thế giới một thời gian trước đây. Nó được thảo luận ở đây trong một bài viết trên blog. Tôi đã sử dụng RavenDB và C # nhưng các chi tiết không liên quan và ý tưởng là như nhau.


7

Những loại máy dữ liệu sẽ được lưu trữ trên? Nó có phải là một thiết bị lưu trữ được chia sẻ?

Yếu tố cuối cùng sẽ quyết định thời gian truy vấn của bạn sẽ là ổ cứng của bạn. Cơ sở dữ liệu và tối ưu hóa truy vấn của chúng được thiết kế để giảm số lượng I / O đĩa càng nhiều càng tốt. Cho rằng bạn chỉ có 3 bảng, điều này sẽ được thực hiện khá đáng tin cậy.

Tốc độ đọc / ghi của ổ cứng sẽ chậm hơn 200-300 lần so với tốc độ bộ nhớ. Tìm kiếm ổ cứng với độ trễ rất nhanh và tốc độ đọc và ghi nhanh. Nếu tất cả dữ liệu này nằm trên một ổ đĩa 2 TB, có lẽ bạn sẽ phải chờ rất lâu để các truy vấn kết thúc. Độ trễ ổ cứng là ~ 10-15 mili giây trong khi độ trễ bộ nhớ nhỏ hơn 10 Nam giây. Độ trễ ổ cứng có thể chậm hơn 1000-2000x so với độ trễ bộ nhớ. Sự di chuyển của cánh tay cơ khí trên ổ cứng là điều TUYỆT VỜI nhất trong toàn bộ hệ thống này.

Bạn có bao nhiêu RAM? 16gb? Hãy nói rằng cho phép bạn giữ 32 hồ sơ. Bạn có 16000 tập tin. Nếu bạn định quét tuyến tính tất cả các điểm dữ liệu, bạn có thể dễ dàng kết thúc với 5-10 giây trong thời gian tìm kiếm một mình. Vậy thì yếu tố nào trong tốc độ truyền 50mb / s? Khoảng 7 giờ. Ngoài ra, mọi dữ liệu được lưu tạm thời sẽ phải được lưu trữ trên ổ cứng để nhường chỗ cho dữ liệu mới được đọc.

Nếu bạn đang sử dụng một thiết bị lưu trữ dùng chung đang được người dùng khác tích cực sử dụng ... thì cách tốt nhất của bạn là sẽ chạy mọi thứ vào ban đêm.

Giảm số lượng truy vấn lồng nhau cũng giúp. Các truy vấn lồng nhau dẫn đến các bảng tạm thời sẽ làm hỏng ổ cứng của bạn hơn nữa. Tôi hy vọng bạn có SỐ LƯỢNG không gian trống trên ổ cứng của mình.

Tối ưu hóa truy vấn chỉ có thể nhìn vào 1 truy vấn tại một thời điểm. Vì vậy, các câu lệnh chọn lồng nhau không thể được tối ưu hóa. TUY NHIÊN, nếu bạn biết một truy vấn lồng nhau cụ thể sẽ dẫn đến một tập dữ liệu nhỏ được trả về, hãy giữ nó. Tối ưu hóa truy vấn sử dụng biểu đồ và các giả định sơ bộ, nếu bạn biết điều gì đó về dữ liệu và truy vấn thì hãy tiếp tục và thực hiện.

Bạn càng biết nhiều về cách lưu trữ dữ liệu của mình trên đĩa, bạn càng có thể viết các truy vấn của mình nhanh hơn. Nếu mọi thứ được lưu trữ tuần tự trên khóa chính, có thể có ích khi sắp xếp các khóa gốc được trả về từ một truy vấn lồng nhau. Ngoài ra, nếu bạn có thể giảm tập hợp các bộ dữ liệu bạn cần phân tích trước, hãy làm điều đó. Tùy thuộc vào hệ thống của bạn, bạn sẽ xem xét khoảng 1 giây truyền dữ liệu cho mỗi tệp.

Nếu bạn sẽ sửa đổi các giá trị Tên (varchars), tôi sẽ thay đổi nó thành một kiểu dữ liệu với kích thước tối đa, nó sẽ ngăn phân mảnh và sự đánh đổi chỉ là một vài byte bộ nhớ. Có thể là một NVARCHAR với tối đa 100.

Theo như các ý kiến ​​về việc không chuẩn hóa bảng. Tôi nghĩ có lẽ tốt nhất là chỉ lưu trữ các điểm dữ liệu trong các nhóm lớn hơn (có thể là phổ) và sau đó thực hiện phân tích dữ liệu bằng python hoặc một ngôn ngữ tương tác với cơ sở dữ liệu. Trừ khi SQL-Wizard của bạn.


3
Bạn nhấn mạnh sự khác biệt lớn về độ cứng của ổ cứng so với độ trễ của bộ nhớ nhưng số của bạn bị giảm đi bởi hệ số 1000. Nếu ổ cứng có độ trễ khoảng 10ms và bộ nhớ 10ns, độ trễ không khác nhau bởi hệ số 1.000 nhưng hệ số là 1.000.000!
Spectre256

6

Đối với tôi nghe có vẻ như một kịch bản sử dụng trong đó bạn muốn một cái gì đó giống như một "cửa hàng cột quan hệ" như được mô tả ở đây .

Tôi có thể đang hiểu nhầm thiết kế, nhưng nếu bạn chủ yếu xử lý một tập hợp lớn các mảng, lưu trữ chúng trong các bảng định hướng hàng điển hình có nghĩa là mỗi phần tử tương tự như một lát cắt. Nếu bạn quan tâm đến việc xem các lát cắt theo cách điển hình, điều đó có ý nghĩa, nhưng nó có thể kém hiệu quả hơn nếu bạn thực sự nhìn vào toàn bộ các cột tại một thời điểm.

Khi truy xuất các mảng, không chỉ bạn có thể không cần nối nó với một bảng khác do quá trình chuẩn hóa của bạn, mà bạn có thể truy xuất chuỗi dưới dạng một mảng thay vì băm.

Tôi thực sự có thể đang hiểu sai vấn đề, và tôi thậm chí không đề xuất một giải pháp cụ thể.

Đây là một cuộc nói chuyện khác có thể có liên quan, ngay cả khi đó không thực sự là một giải pháp hiện tại hoặc có thể triển khai.


6

Tôi khuyên bạn nên thử và phân vùng bảng của bạn. Chúng tôi có hơn 80 triệu hàng trong một bảng (dữ liệu thị trường chứng khoán) và không gặp khó khăn khi truy cập nó nhanh chóng.

Tùy thuộc vào cách bạn định tìm kiếm dữ liệu của mình, bạn nên thiết kế phân vùng của mình. Trong trường hợp của chúng tôi theo ngày hoạt động tốt bởi vì chúng tôi truy vấn cho các ngày cụ thể.

http://dev.mysql.com/doc/refman/5.1/en/partitioning-limemony.html

http://www.sl slideshoware.net/datacharmer/mysql-partitions-tutorial


5

Đúng nhưng...

Tôi đã làm việc với các bảng có 2 tỷ hàng. Tuy nhiên, chỉ có các truy vấn sử dụng PK được mong đợi là nhanh.

Quan trọng nhất, phần cứng có đủ RAM để phù hợp với toàn bộ bảng trong bộ nhớ. Khi điều đó trở thành một vấn đề (tối đa 96GB tại thời điểm đó), đã đi phân vùng dọc, giữ kích thước của bảng được đặt trên mỗi máy đủ nhỏ để vẫn vừa trong bộ nhớ. Ngoài ra, các máy được kết nối thông qua cáp quang 10Gb, do đó, thông lượng mạng không phải là vấn đề lớn.

BTW. lược đồ của bạn trông giống như một cái gì đó, có thể phù hợp với giải pháp NoQuery, sử dụng run_idlàm khóa băm cho phổ và spectrum_idlàm băm cho các điểm dữ liệu.


4

Tôi đã viết về chủ đề này trên blog của mình: http://www.tocker.ca/2013/10/24/improving-the-performance-of-large-tables-in-MyQuery.html

Để lặp lại một số điểm chính:

  • Cây B xuống cấp khi chúng lớn hơn và không vừa với bộ nhớ (MySQL không đơn độc ở đây).
  • InnoDB có một số tính năng để giúp duy trì hiệu suất (thay đổi bộ đệm; trước đây được gọi là 'bộ đệm chèn').
  • Phân vùng cũng có thể giúp đỡ.

Trong các bình luận về bài đăng của tôi, Tim Callaghan đã liên kết với điều này: http://www.tokutek.com/resource/benchmark-results/benchmark-vs-innodb-hdds/#iiBench

Hiển thị chèn 1 tỷ hàng bằng cách sử dụng điểm chuẩn iibench.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.