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.
(value_name varchar(20), value double)
sẽ có thể lưu trữ tất cả mọi thứ (value_name
bịf1
,f2
...)