thiết kế bảng / chỉ mục mysql hiệu quả cho 35 triệu hàng + bảng, với hơn 200 cột tương ứng (gấp đôi), bất kỳ kết hợp nào trong số đó có thể được truy vấn


17

Tôi đang tìm kiếm lời khuyên về thiết kế bảng / chỉ mục cho tình huống sau:

Tôi có một bảng lớn (dữ liệu lịch sử giá cổ phiếu, InnoDB, 35 triệu hàng và đang phát triển) với khóa chính tổng hợp (propertyid (int), ngày (ngày)). Ngoài thông tin về giá, tôi có 200 giá trị gấp đôi cần tương ứng với mỗi bản ghi.

CREATE TABLE `mytable` (
`assetid` int(11) NOT NULL,
`date` date NOT NULL,
`close` double NOT NULL,
`f1` double DEFAULT NULL,   
`f2` double DEFAULT NULL,
`f3` double DEFAULT NULL,   
`f4` double DEFAULT NULL,
 ... skip a few 
`f200` double DEFAULT NULL, 
PRIMARY KEY (`assetid`, `date`)) ENGINE=`InnoDB` DEFAULT CHARACTER SET latin1 COLLATE
    latin1_swedish_ci ROW_FORMAT=COMPACT CHECKSUM=0 DELAY_KEY_WRITE=0 
    PARTITION BY RANGE COLUMNS(`date`) PARTITIONS 51;

ban đầu tôi đã lưu trữ 200 cột đôi trực tiếp trong bảng này để dễ cập nhật và truy xuất, và điều này đã hoạt động tốt, vì truy vấn duy nhất được thực hiện trên bảng này là theo tài sản và ngày (chúng được bao gồm trong bất kỳ truy vấn nào trong bảng này ) và 200 cột đôi chỉ được đọc. Kích thước cơ sở dữ liệu của tôi là khoảng 45 Gig

Tuy nhiên, bây giờ tôi có yêu cầu tôi cần có thể truy vấn bảng này bằng bất kỳ sự kết hợp nào của 200 cột này (có tên là F1, f2, ... f200), ví dụ:

select from mytable 
where assetid in (1,2,3,4,5,6,7,....)
and date > '2010-1-1' and date < '2013-4-5'
and f1 > -0.23 and f1 < 0.9
and f117 > 0.012 and f117 < .877
etc,etc

Trước đây tôi chưa từng phải đối phó với lượng dữ liệu lớn này, vì vậy, bản năng đầu tiên của tôi là chỉ số là cần thiết cho mỗi 200 cột này, hoặc tôi sẽ cuộn lên với các bảng quét lớn, v.v. tôi cần một bảng cho mỗi trong số 200 cột với khóa chính, giá trị và lập chỉ mục các giá trị. Vì vậy, tôi đã đi với điều đó.

CREATE TABLE `f1` (
`assetid` int(11) NOT NULL DEFAULT '0',
`date` date NOT NULL DEFAULT '0000-00-00',
`value` double NOT NULL DEFAULT '0',
PRIMARY KEY (`assetid`, `date`),
INDEX `val` (`value`)
) ENGINE=`InnoDB` DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci ROW_FORMAT=COMPACT CHECKSUM=0 DELAY_KEY_WRITE=0;

tôi điền và lập chỉ mục tất cả 200 bảng. Tôi đã để nguyên bảng chính với tất cả 200 cột, vì thường xuyên nó được truy vấn trên phạm vi ngày và tài sản và tất cả 200 cột được chọn. Tôi hình dung rằng việc để các cột đó trong bảng cha (không được lập trình) cho mục đích đọc và sau đó thêm chúng vào chỉ mục trong các bảng của riêng chúng (để lọc tham gia) sẽ hiệu quả nhất. Tôi đã chạy giải thích về hình thức mới của truy vấn

select count(p.assetid) as total 
from mytable p 
inner join f1 f1 on f1.assetid = p.assetid and f1.date = p.date
inner join f2 f2 on f2.assetid = p.assetid and f2.date = p.date 
where p.assetid in(1,2,3,4,5,6,7)
and p.date >= '2011-01-01' and p.date < '2013-03-14' 
and(f1.value >= 0.96 and f1.value <= 0.97 and f2.value >= 0.96 and f2.value <= 0.97) 

Thật vậy, kết quả mong muốn của tôi đã đạt được, giải thích cho tôi thấy rằng các hàng được quét nhỏ hơn nhiều cho truy vấn này. Tuy nhiên tôi cố gắng với một số tác dụng phụ không mong muốn.

1) cơ sở dữ liệu của tôi đã tăng từ 45 Gig lên 110 Gig. Tôi không còn có thể giữ db trong RAM. (tuy nhiên tôi có 256Gig RAM trên đường)

2) việc chèn dữ liệu mới hàng đêm cần được thực hiện 200 lần thay vì một lần

3) bảo trì / chống phân mảnh của 200 bảng mới mất nhiều thời gian hơn 200 lần so với chỉ 1 bảng. Nó không thể được hoàn thành trong một đêm.

4) các truy vấn đối với các bảng F1, vv không nhất thiết phải thực hiện. ví dụ:

 select min(value) from f1 
 where assetid in (1,2,3,4,5,6,7) 
 and date >= '2013-3-18' and date < '2013-3-19'

truy vấn trên, trong khi giải thích cho thấy rằng nó tìm kiếm ở <1000 hàng, có thể mất hơn 30 giây để hoàn thành. Tôi cho rằng điều này là do các chỉ số quá lớn để phù hợp với bộ nhớ.

Vì đó là rất nhiều tin xấu, tôi nhìn xa hơn và tìm thấy phân vùng. Tôi đã thực hiện các phân vùng trên bảng chính, được phân vùng vào ngày 3 tháng một lần. Hàng tháng dường như có ý nghĩa với tôi nhưng tôi đã đọc rằng một khi bạn nhận được hơn 120 phân vùng hoặc hơn, hiệu suất bị ảnh hưởng. phân vùng hàng quý sẽ để lại cho tôi dưới đó trong 20 năm tới hoặc lâu hơn. mỗi phân vùng là một chút dưới 2 Gig. Tôi đã giải thích các phân vùng và mọi thứ dường như được cắt tỉa đúng cách, vì vậy bất kể tôi cảm thấy phân vùng là một bước tốt, ít nhất là cho mục đích phân tích / tối ưu hóa / sửa chữa.

Tôi đã dành rất nhiều thời gian với bài viết này

http://ftp.nchu.edu.tw/MySQL/tech-resource/articles/testing-partitions-large-db.html

bảng của tôi hiện đang được phân vùng với khóa chính vẫn còn trên đó. Bài viết đề cập rằng các khóa chính có thể làm cho bảng được phân vùng chậm hơn, nhưng nếu bạn có một máy có thể xử lý nó, các khóa chính trên bảng được phân đoạn sẽ nhanh hơn. Biết tôi có một máy lớn trên đường (RAM 256 G), tôi đã để lại các phím.

Vì vậy, như tôi thấy, đây là lựa chọn của tôi

lựa chọn 1

1) xóa 200 bảng bổ sung và để truy vấn quét bảng để tìm các giá trị F1, f2, v.v. các chỉ mục không duy nhất thực sự có thể ảnh hưởng đến hiệu suất trên một bảng được phân vùng chính xác. chạy một giải thích trước khi người dùng chạy truy vấn và từ chối chúng nếu số lượng hàng được quét vượt quá ngưỡng tôi xác định. tự cứu mình khỏi nỗi đau của cơ sở dữ liệu khổng lồ. Heck, tất cả sẽ sớm trong bộ nhớ.

câu hỏi phụ:

Có vẻ như tôi đã chọn một sơ đồ phân vùng thích hợp?

Lựa chọn 2

Phân vùng tất cả 200 bảng bằng cách sử dụng sơ đồ 3 tháng giống nhau. thưởng thức các hàng quét nhỏ hơn và cho phép người dùng chạy các truy vấn lớn hơn. bây giờ chúng được phân vùng ít nhất tôi có thể quản lý chúng 1 phân vùng tại một thời điểm cho mục đích bảo trì. Heck, tất cả sẽ sớm trong bộ nhớ. Phát triển cách hiệu quả để cập nhật chúng hàng đêm.

câu hỏi phụ:

Bạn có thấy một lý do mà tôi có thể tránh các chỉ mục khóa chính trên các bảng F1, f2, f3, f4 ... này không, khi biết rằng tôi luôn có tài sản và ngày tháng khi truy vấn? có vẻ phản trực giác với tôi nhưng tôi không quen với các tập dữ liệu có kích thước này. điều đó sẽ thu hẹp cơ sở dữ liệu một bó tôi giả sử

Lựa chọn 3

Thả các cột F1, f2, f3 vào bảng chính để lấy lại khoảng trống đó. thực hiện 200 lần tham gia nếu tôi cần đọc 200 tính năng, có thể nó sẽ không chậm như âm thanh.

Lựa chọn 4

Tất cả các bạn có một cách tốt hơn để cấu trúc này hơn tôi nghĩ cho đến nay.

* LƯU Ý: Tôi sẽ sớm thêm 50-100 giá trị kép này vào mỗi mục, vì vậy tôi cần thiết kế để biết rằng điều đó sẽ đến.

Cảm ơn vì tất cả sự giúp đỡ

Cập nhật số 1 - 24/03/2013

Tôi đã đi với ý tưởng được đề xuất trong các ý kiến ​​tôi nhận được bên dưới và tạo một bảng mới với thiết lập sau:

create table 'features'{
  assetid int,
  date    date,
  feature varchar(4),
  value   double
}

Tôi phân vùng bảng trong khoảng thời gian 3 tháng.

Tôi đã lấy đi 200 bảng trước đó để cơ sở dữ liệu của tôi giảm xuống còn 45 Gig và bắt đầu điền vào bảng mới này. Một ngày rưỡi sau, nó đã hoàn thành và cơ sở dữ liệu của tôi bây giờ nằm ​​ở 220 Gigs mũm mĩm !

Nó không cho phép loại bỏ 200 giá trị này khỏi bảng chính, vì tôi có thể lấy chúng từ một lần tham gia, nhưng điều đó thực sự chỉ mang lại cho tôi 25 Gigs hoặc có thể

Tôi đã yêu cầu nó tạo ra một khóa chính về tài sản, ngày tháng, tính năng và chỉ số về giá trị, và sau 9 giờ đồng hồ, nó thực sự không tạo ra vết lõm và dường như đóng băng nên tôi đã giết chết phần đó.

Tôi đã xây dựng lại một vài phân vùng nhưng dường như nó không lấy lại được nhiều / bất kỳ khoảng trống nào.

Vì vậy, giải pháp đó có vẻ như sẽ không lý tưởng. Các hàng có chiếm nhiều không gian hơn đáng kể so với các cột tôi tự hỏi, đó có thể là lý do tại sao giải pháp này chiếm nhiều không gian hơn không?

Tôi đã xem qua bài viết này:

http://www.chrismoos.com/2010/01/31/mysql-partitioning-tables-with-millions-of-rows

nó đã cho tôi một ý tưởng. Nó nói rằng:

Lúc đầu, tôi nghĩ về phân vùng RANGE theo ngày và trong khi tôi đang sử dụng ngày trong các truy vấn của mình, thì một truy vấn có phạm vi ngày rất lớn và điều đó có nghĩa là nó có thể dễ dàng mở rộng tất cả các phân vùng.

Bây giờ tôi cũng đang phân vùng phạm vi theo ngày, nhưng cũng sẽ cho phép tìm kiếm theo phạm vi ngày lớn, điều này sẽ làm giảm hiệu quả của phân vùng của tôi. Tôi sẽ luôn có một phạm vi ngày khi tôi tìm kiếm, tuy nhiên tôi cũng sẽ luôn có một danh sách các tài sản. Có lẽ giải pháp của tôi là phân vùng theo tài sản và ngày tháng, nơi tôi xác định các phạm vi tài sản thường được tìm kiếm (mà tôi có thể đưa ra, có các danh sách tiêu chuẩn, S & P 500, Russell 2000, v.v.). Bằng cách này, tôi gần như không bao giờ nhìn vào toàn bộ tập dữ liệu.

Sau đó, một lần nữa, tôi là chìa khóa chính về tài sản và ngày tháng dù sao, vì vậy có lẽ điều đó sẽ không giúp được gì nhiều.

Bất kỳ suy nghĩ / ý kiến ​​sẽ được đánh giá cao.


2
Tôi không thấy lý do tại sao bạn cần 200 bảng. Một bảng duy nhất với (value_name varchar(20), value double)sẽ có thể lưu trữ tất cả mọi thứ ( value_namebị f1, f2...)
a_horse_with_no_name

cảm ơn. lý do tôi đặt chúng riêng lẻ là để đạt được giới hạn 50 chỉ mục trên một bảng. Tôi đã nghĩ về việc đặt chúng vào 5 bảng, mỗi 40 giá trị, nhưng tôi đang chèn 17000 bản ghi mỗi ngày cho mỗi bảng và không biết hiệu suất chèn sẽ như thế nào trên một bảng có 40 chỉ mục. lưu ý rằng mỗi kết hợp của tài sản, ngày sẽ có các giá trị F1, f2 ... của riêng nó. Bạn có đang đề xuất một bảng duy nhất với (propertyid, date, value_name, value), với khóa chính là propertyid, date, có thể là chỉ mục trên (value_name, value) không? bảng đó sẽ có 35 triệu * 200 = 7 tỷ hàng nhưng có thể phân vùng tốt sẽ hoạt động?
dyeryn

bài đăng được cập nhật với kinh nghiệm của tôi khi thử phương pháp này
dyeryn

Tôi có giải pháp cuối cùng trong quá trình phát triển, tôi sẽ cập nhật khi hoàn thành. về cơ bản, đây là giải pháp bảng duy nhất được đề xuất ở đây với phân vùng cụ thể và ngăn chặn logic.
dyeryn

Có thể giúp một công cụ lưu trữ khác nhau? Thay vì InnoDb có thể thử InfiniDB? Dữ liệu cột, các mẫu truy cập trông giống như cập nhật hàng loạt lớn, đọc dựa trên phạm vi và bảo trì bảng tối thiểu.
lộn xộn

Câu trả lời:


1

Thật trùng hợp, tôi cũng đang xem xét một trong những hỗ trợ khách hàng nơi chúng tôi đã thiết kế cấu trúc cặp khóa-giá trị để linh hoạt và hiện tại bảng có hơn 1,5B hàng và ETL quá chậm. cũng có rất nhiều thứ khác trong trường hợp của tôi nhưng bạn có nghĩ về thiết kế đó không. bạn sẽ có một hàng với tất cả 200 cột giá trị hiện tại, hàng đó sẽ chuyển đổi thành 200 hàng trong thiết kế cặp Khóa-Giá trị. bạn sẽ có được lợi thế về không gian với thiết kế này tùy thuộc vào một AssetID nhất định và Ngày có bao nhiêu hàng thực sự có tất cả các giá trị 200 f1 đến f200? nếu bạn nói các cột od 30% thậm chí có giá trị NULL thì đó là tiết kiệm không gian của bạn. bởi vì trong thiết kế cặp khóa-giá trị nếu id giá trị NULL hàng đó không cần phải ở trong bảng. nhưng trong thiết kế cấu trúc cột hiện có, ngay cả NULL cũng cần không gian. (Tôi không chắc chắn 100% nhưng nếu bạn có nhiều hơn 30 cột NULL trong bảng thì NULL mất 4byte). nếu bạn thấy thiết kế này và giả sử rằng tất cả các hàng 35M có giá trị trong tất cả 200 cột thì db hiện tại của bạn sẽ trở thành 200 * 35M = 700M hàng trong bảng ngay lập tức. nhưng nó sẽ không cao trong không gian bảng như những gì bạn có với tất cả các cột trong một bảng vì chúng ta chỉ chuyển các Cột thành hàng. trong hoạt động chuyển vị này thực sự chúng ta sẽ không có các hàng trong đó các giá trị là NULL. vì vậy bạn thực sự có thể chạy truy vấn đối với bảng này và xem có bao nhiêu null ở đó và ước tính kích thước bảng mục tiêu của bạn trước khi bạn thực sự thực hiện nó. nhưng nó sẽ không cao trong không gian bảng như những gì bạn có với tất cả các cột trong một bảng vì chúng ta chỉ chuyển các Cột thành hàng. trong hoạt động chuyển vị này thực sự chúng ta sẽ không có các hàng trong đó các giá trị là NULL. vì vậy bạn thực sự có thể chạy truy vấn đối với bảng này và xem có bao nhiêu null ở đó và ước tính kích thước bảng mục tiêu của bạn trước khi bạn thực sự thực hiện nó. nhưng nó sẽ không cao trong không gian bảng như những gì bạn có với tất cả các cột trong một bảng vì chúng ta chỉ chuyển các Cột thành hàng. trong hoạt động chuyển vị này thực sự chúng ta sẽ không có các hàng trong đó các giá trị là NULL. vì vậy bạn thực sự có thể chạy truy vấn đối với bảng này và xem có bao nhiêu null ở đó và ước tính kích thước bảng mục tiêu của bạn trước khi bạn thực sự thực hiện nó.

lợi thế thứ hai là hiệu suất đọc. như bạn đã đề cập rằng cách truy vấn dữ liệu mới là bất kỳ sự kết hợp nào giữa cột từ F1 đến f200 này trong mệnh đề where. với cặp giá trị khóa thiết kế từ F1 đến f200 có trong một cột, hãy nói "FildName" và các giá trị của chúng hiện diện trong cột thứ hai cho phép nói "FieldValue". bạn có thể có chỉ mục CLUSTERED trên cả hai cột. truy vấn của bạn sẽ là UNION của những lựa chọn đó.

WHERE (FiledName = 'f1' và FieldValue GIỮA 5 VÀ 6)

LIÊN HIỆP

(FiledName = 'f2' và FieldValue GIỮA 8 VÀ 10)

Vân vân.....

Tôi sẽ cung cấp cho bạn một số số hiệu suất từ ​​máy chủ prod thực tế. chúng tôi có 75 cột giá cho mỗi VÉ bảo mật.


1

Khi xử lý loại dữ liệu này khi bạn cần chèn nhiều hàng và bạn cũng cần hiệu năng truy vấn phân tích thực sự tốt (tôi giả định rằng đây là trường hợp ở đây), bạn có thể thấy rằng RDBMS cột là phù hợp . Hãy xem Infobright CE và InfiniDB CE (cả hai công cụ lưu trữ cột được cắm vào MySQL) và Vertica CE cũng vậy (giống như PostgreQuery thay vì giống MySQL) ... tất cả các Phiên bản cộng đồng này đều miễn phí (mặc dù Vertica không mã nguồn mở, nó mở rộng tới 3 nút và 1Tb dữ liệu miễn phí). Thông thường RDBMS của cột cung cấp thời gian phản hồi "truy vấn lớn" tốt hơn 10 - 100 lần so với dựa trên hàng và thời gian tải tốt hơn 5-50X. Bạn phải sử dụng chúng một cách chính xác hoặc chúng bốc mùi (không thực hiện các thao tác một hàng ... thực hiện tất cả các hoạt động theo cách tiếp cận hàng loạt), nhưng sử dụng đúng cách chúng thực sự gây rung chuyển. ;-)

HTH, Dave Sisk


1
Chúng tôi có gần một tỷ hàng dữ liệu loại nhấp chuột (không khác với dữ liệu đánh dấu chứng khoán) trong cài đặt Vertica 3 nút ... chúng tôi có thể tải dữ liệu cả ngày trong khoảng 15 giây và chúng tôi nhận được thời gian phản hồi truy vấn trong phạm vi 500 mili giây. Trong trường hợp của bạn, nó chắc chắn có vẻ như điều này sẽ đáng xem.
Dave Sisk

Tôi có thể chứng minh cho cùng. Tại công ty cuối cùng của chúng tôi, chúng tôi đã có một cụm Vertica 8 nút với cùng số lượng hàng và các truy vấn tổng hợp đơn giản trên toàn bộ được trả về sau 1-3 giây (trung bình). Đó là khoảng 1/4 chi phí của cụm Greenplum trước đây của chúng tôi.
bma
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.