Truy vấn chậm trên chỉ mục hàng tỷ-hàng-bảng // được sử dụng


10

Vì tôi là một nhà phát triển trẻ và không thực sự có kỹ năng sử dụng cơ sở dữ liệu (PostgreQuery 9.3), tôi đã gặp một số vấn đề với một dự án, nơi tôi thực sự cần sự giúp đỡ.

Dự án của tôi là về việc thu thập dữ liệu từ các thiết bị (tối đa 1000 thiết bị trở lên), trong đó mỗi thiết bị đang gửi một khối dữ liệu mỗi giây, tạo ra khoảng 3 triệu hàng mỗi giờ.

Hiện tại tôi có một bảng lớn nơi tôi lưu trữ dữ liệu đến của mọi thiết bị:

CREATE TABLE data_block(
    id bigserial
    timestamp timestamp
    mac bigint
)

Vì có một số loại dữ liệu mà một khối dữ liệu có thể (hoặc không thể) bao gồm, nên có các bảng khác tham chiếu data_blockbảng.

CREATE TABLE dataA(
    data_block_id bigserial
    data

    CONSTRAINT fkey FOREIGN KEY (data_block_id) REFERENCES data_block(id);
);
CREATE TABLE dataB(...);
CREATE TABLE dataC(...);
CREATE INDEX index_dataA_block_id ON dataA (data_block_id DESC);
...

Có thể trong một data_block có 3x dataA, 1x dataB, nhưng không có dataC.

Dữ liệu sẽ được lưu giữ trong vài tuần, vì vậy tôi sẽ có ~ 5 tỷ hàng trong bảng này. Hiện tại, tôi có ~ 600 triệu hàng trong bảng và các truy vấn của tôi mất một thời gian rất dài. Vì vậy, tôi quyết định tạo một chỉ mục trên timestampmacbởi vì các câu lệnh chọn của tôi luôn truy vấn theo thời gian và thường theo thời gian + mac.

CREATE INDEX index_ts_mac ON data_block (timestamp DESC, mac);

... nhưng các truy vấn của tôi vẫn mất nhiều thời gian. Ví dụ: tôi đã truy vấn dữ liệu trong một ngày và một mac:

SELECT * FROM data_block 
WHERE timestamp>'2014-09-15' 
AND timestamp<'2014-09-17' 
AND mac=123456789
Index Scan using index_ts_mac on data_block  (cost=0.57..957307.24 rows=315409 width=32) (actual time=39.849..334534.972 rows=285857 loops=1)
  Index Cond: ((timestamp > '2014-09-14 00:00:00'::timestamp without time zone) AND (timestamp < '2014-09-16 00:00:00'::timestamp without time zone) AND (mac = 123456789))
Total runtime: 334642.078 ms

Tôi đã làm một chân không đầy đủ trước khi chạy truy vấn. Có cách nào hay để giải quyết vấn đề như vậy với các bảng lớn để thực hiện truy vấn <10 giây không?

Tôi đã đọc về phân vùng, nhưng điều này sẽ không hoạt động với các tham chiếu dataA, dataB, dataC của tôi đến data_block_id phải không? Nếu nó hoạt động bằng cách nào đó, tôi nên tạo phân vùng theo thời gian hoặc qua mac?

Tôi đã thay đổi chỉ số của tôi sang hướng khác. MAC đầu tiên, sau đó là dấu thời gian và nó đạt được rất nhiều hiệu suất.

CREATE INDEX index_mac_ts ON data_block (mac, timestamp DESC);

Tuy nhiên, các truy vấn mất> 30 giây. Đặc biệt là khi tôi làm một LEFT JOINvới các bảng dữ liệu của tôi. Đây là một EXPLAIN ANALYZEtrong những truy vấn với chỉ mục mới:

EXPLAIN ANALYZE SELECT * FROM data_block WHERE mac = 123456789 AND timestamp < '2014-10-05 00:00:00' AND timestamp > '2014-10-04 00:00:00'
Bitmap Heap Scan on data_block  (cost=1514.57..89137.07 rows=58667 width=28) (actual time=2420.842..32353.678 rows=51342 loops=1)
  Recheck Cond: ((mac = 123456789) AND (timestamp < '2014-10-05 00:00:00'::timestamp without time zone) AND (timestamp > '2014-10-04 00:00:00'::timestamp without time zone))
  ->  Bitmap Index Scan on index_mac_ts  (cost=0.00..1499.90 rows=58667 width=0) (actual time=2399.291..2399.291 rows=51342 loops=1)
        Index Cond: ((mac = 123456789) AND (timestamp < '2014-10-05 00:00:00'::timestamp without time zone) AND (timestamp > '2014-10-04 00:00:00'::timestamp without time zone))
Total runtime: 32360.620 ms 

Thật không may phần cứng của tôi bị hạn chế nghiêm ngặt. Tôi đang sử dụng Intel i3-2100 @ 3.10Ghz, RAM 4GB. Cài đặt hiện tại của tôi như sau:

default_statistics_target = 100
maintenance_work_mem = 512MB
constraint_exclusion = on
checkpoint_completion_target = 0.9
effective_cache_size = 4GB
work_mem = 512MB
wal_buffers = 16MB
checkpoint_segments = 32
shared_buffers = 2GB
max_connections = 20
random_page_cost = 2

Câu trả lời:


1

Điều này có thể phản ánh sự thiên vị MS SQL của tôi, nhưng tôi sẽ thử phân cụm bảng theo timestamp. Nếu bạn thường xuyên kéo dữ liệu trong một khoảng thời gian cụ thể, điều này sẽ giúp ích vì dữ liệu sẽ được lưu trữ liên tục về mặt vật lý. Hệ thống có thể tìm đến điểm bắt đầu, quét đến cuối phạm vi và được thực hiện. Nếu bạn đang truy vấn trong một giờ cụ thể, đó chỉ là 3.600.000 hồ sơ.

Nếu truy vấn của bạn (đó là ...?) Dành cho một máy cụ thể, Postgres sau đó sẽ cần lọc 99,9% trong số các bản ghi 3,6 M đó. Nếu bộ lọc một nghìn này được chọn nhiều hơn bộ điều chỉnh phạm vi ngày thông thường, bạn nên sử dụng trường chọn nhiều hơn maclàm thành phần đầu tiên trong chỉ mục của mình. Nó có thể vẫn còn giá trị phân cụm.

Nếu vẫn không được, tôi sẽ phân vùng theo cùng một trường mà bạn đang lập chỉ mục, timestamphoặc mac.

Bạn đã không cung cấp cho các loại dữ liệu. Chúng có phù hợp với dữ liệu không? Lưu trữ ngày dưới dạng văn bản sẽ không cần thiết làm phồng bảng của bạn, ví dụ.


2
Postgres không có các chỉ mục được nhóm (mặc dù nó có thể phân cụm một bảng dọc theo một chỉ mục - nhưng điều đó cần được thực hiện thủ công và sẽ không "ở lại")
a_horse_with_no_name

cám ơn bạn đã cho lời khuyên. bây giờ nó chạy nhanh hơn trước, nhưng vẫn ở hiệu suất rất thấp> 30 giây cho mỗi truy vấn. tôi cũng đã phân cụm, nhưng như @a_horse_with_no_name đã nói: trong postgres, đây là một shot. loại dữ liệu của tôi là đúng tôi nghĩ. tôi đã thêm chúng trong câu hỏi
manman

Nếu không có các bảng được nhóm, đề xuất tiếp theo của tôi cho các truy vấn phạm vi sẽ được phân vùng.
Jon của tất cả các giao dịch

-2

Tôi đã làm việc trên một ứng dụng có hàng tỷ bài đọc từ công tơ điện và thực hiện hầu hết các truy vấn trong vòng dưới 10 giây.

Môi trường của chúng tôi đã khác Microsoft SQL Server trên máy lớp máy chủ (4 lõi, bộ nhớ 24 GB). Bất kỳ cơ hội để nâng cấp lên một máy chủ?

Một vấn đề lớn là việc đọc từng bài đọc một lần có tác động lớn đến cơ sở dữ liệu. Viết dữ liệu yêu cầu khóa và truy vấn sẽ chờ. Bạn có thể thực hiện chèn theo lô?

Với lược đồ của bạn, bạn sẽ có 4 bảng rất lớn. Điều quan trọng là tất cả các tham gia của bạn sử dụng các chỉ mục trên cả hai bảng. Quét bảng sẽ mất mãi mãi. Có khả thi để hợp nhất chúng thành 1 bảng với các trường có khả năng không?


chèn theo lô: tôi có thể thực hiện chèn hàng loạt nhưng hiện tại tôi đang làm việc trên cơ sở dữ liệu thử nghiệm, trong đó không có chèn nào được thực hiện trong khi truy vấn đang chạy. nhưng cảm ơn bạn tôi sẽ nghĩ về điều đó sau :) chỉ số: tôi có chỉ mục trên mỗi bảng. trên bảng dữ liệu một chỉ mục trên id, trên bảng data_block trên (mac, dấu thời gian). vấn đề cũng có khi tôi đang tìm kiếm dataA cho mỗi lần tham gia trái nhưng không có. ngay cả với chỉ mục, nó tìm kiếm các bảng dữ liệu. Các trường không thể : không thể thực hiện được vì data_block có thể có nhiều dữ liệu thuộc một loại. 1xdata_block -> 4xdataA, vd
manman

Công cụ DB của bạn có cung cấp cho bạn một bộ phân tích truy vấn không? Bạn có thể cần một chỉ mục trên data_block dựa trên id.
KC-NH

Tôi sẽ thử, nhưng tôi không hiểu tại sao điều này có thể giúp!?
đàn ông

-2

Bạn đang đạt các giới hạn khả năng mở rộng vốn có của Postgres (hoặc bất kỳ RDBMS nào khác).

Hãy nhớ rằng chỉ mục RDBMS là B-Tree. Cây B là O (log n) cho cả trường hợp trung bình và xấu nhất. Điều này làm cho nó trở thành một lựa chọn tốt, an toàn, có thể dự đoán được cho các giá trị hợp lý của N. Nó bị phá vỡ khi N quá lớn.

Cơ sở dữ liệu NoQuery là (đối với hầu hết các phần) bảng băm. Bảng băm là O (1) trong trường hợp trung bình và O (n) trong trường hợp xấu nhất. Giả sử bạn có thể tránh trường hợp xấu nhất, nó thực hiện rất tốt đối với các giá trị rất lớn của N.

Ngoài ra, bảng băm dễ dàng song song và cây b thì không. Điều này làm cho các bảng băm phù hợp hơn với kiến ​​trúc điện toán phân tán.

Khi bạn bắt đầu nhận được hàng tỷ bảng hàng, đã đến lúc xem xét chuyển từ RDBMS sang NoQuery. Cassandra có lẽ sẽ là một lựa chọn tốt cho trường hợp sử dụng của bạn.


2
Rất nhiều RDBMS có nhiều tùy chọn hơn các chỉ mục B-tree (hàm băm, bitmap và các tùy chọn khác). Một số DBMS đang lưu trữ các hàng và một số đang lưu trữ các cột. Và O (logn) không tệ, thậm chí cho hàng tỷ hàng. Và họ không thể đạt được bất kỳ giới hạn nào khi họ đang sử dụng máy nhớ 4GB.
ypercubeᵀᴹ
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.