Dung lượng tệp lớn (80GB) bằng cách nào để tăng tốc độ?


113
 grep -i -A 5 -B 5 'db_pd.Clients'  eightygigsfile.sql

Điều này đã chạy trong một giờ trên một máy chủ linux khá mạnh mẽ mà không bị quá tải. Bất kỳ thay thế cho grep? Bất cứ điều gì về cú pháp của tôi có thể được cải thiện, (ví dụ :rep, fgrep tốt hơn?)

Tệp thực sự nằm trong một thư mục được chia sẻ với một máy chủ khác nhưng không gian đĩa thực sự là cục bộ nên điều đó không tạo ra bất kỳ sự khác biệt nào?

grep đang chiếm tới 93% CPU


8
Tùy thuộc vào ngôn ngữ của bạn, -inút chuyển có thể làm chậm quá trình, thử không -ihoặc có LC_ALL=C grep .... Ngoài ra, nếu bạn chỉ tìm kiếm một chuỗi cố định, hãy sử dụng grep -F.
Thor

5
Như @dogbane đã đề cập việc sử dụng biến LC_ALL = C cùng với fgrep có thể tăng tốc tìm kiếm của bạn, tôi đã thực hiện một số thử nghiệm và có thể đạt được mức tăng hiệu suất 1400% và đã viết một bài viết chi tiết tại sao điều này lại có trong bài đăng grep của tôi
JacobN

Tôi tò mò - tệp có kích thước 80GB là gì? Tôi muốn nghĩ rằng khi một tệp lớn đến mức đó, có thể có một chiến lược lưu trữ tốt hơn (ví dụ: xoay các tệp nhật ký hoặc phân loại theo thứ bậc thành các tệp và thư mục khác nhau). Ngoài ra, nếu các thay đổi chỉ xảy ra ở một số vị trí nhất định của tệp (ví dụ: ở phần cuối), thì chỉ cần lưu trữ một số kết quả grep từ phần trước đó không thay đổi và thay vì ghi xám tệp gốc, hãy lưu trữ tệp kết quả được lưu trữ.
Sridhar Sarnobat

Tôi đã giải quyết trên github.com/google/codesearch - cả lập chỉ mục và tìm kiếm đều nhanh như chớp (được viết bằng Go). cindex .để lập chỉ mục thư mục hiện tại của bạn, sau đó csearch db_pd.Clients.
ccpizza

1
Nếu tệp của bạn đã được lập chỉ mục hoặc sắp xếp, việc này có thể được thực hiện nhanh hơn rất nhiều . Tìm kiếm mỗi dòng là O (n) theo định nghĩa, trong khi một tệp được sắp xếp có thể được tìm kiếm bằng cách chia đôi nó - tại thời điểm đó bạn sẽ nói trong một giây để tìm kiếm 80gb của mình (do đó tại sao một cơ sở dữ liệu được lập chỉ mục 80gb không mất nhiều thời gian cho một SELECT đơn giản, trong khi grep của bạn mất ... tốt, miễn là nó mất).
Charles Duffy,

Câu trả lời:


148

Dưới đây là một số tùy chọn:

1) Đặt tiền tố cho lệnh grep của bạn LC_ALL=Cđể sử dụng ngôn ngữ C thay vì UTF-8.

2) Sử dụng fgrepvì bạn đang tìm kiếm một chuỗi cố định, không phải một biểu thức chính quy.

3) Loại bỏ -itùy chọn, nếu bạn không cần.

Vì vậy, lệnh của bạn trở thành:

LC_ALL=C fgrep -A 5 -B 5 'db_pd.Clients' eightygigsfile.sql

Nó cũng sẽ nhanh hơn nếu bạn sao chép tệp của mình vào đĩa RAM.


5
nhanh hơn NHIỀU bởi một thứ tự cường độ cảm ơn. BTW Tôi đã thêm -n để lấy số dòng. Cũng có thể là một -m để thoát sau trận đấu
zzapper

5
Chà, cảm ơn rất nhiều @dogbane mẹo hay! Điều này dẫn tôi xuống một đường hầm nghiên cứu để tìm hiểu lý do tại sao LC_ALL = C lại tăng tốc độ grep và đó là một trải nghiệm rất thú vị!
JacobN

7
Một số người (không phải tôi) như grep -Fhơnfgrep
Walter Tross

2
Sự hiểu biết của tôi là LANG=C(thay vì LC_ALL=C) là đủ, và dễ nhập hơn.
Walter Tross

2
@Adrian fgreplà một cách khác để viết grep -F, như man fgrepsẽ cho bạn biết. Một số phiên bản của nó mancũng nói rằng cái trước không còn được dùng nữa cho cái sau, nhưng dạng ngắn hơn quá tiện lợi để chết.
Walter Tross

36

Nếu bạn có một CPU đa lõi, tôi thực sự khuyên bạn nên sử dụng song song GNU . Để grep một tệp lớn trong sử dụng song song:

< eightygigsfile.sql parallel --pipe grep -i -C 5 'db_pd.Clients'

Tùy thuộc vào đĩa và CPU của bạn, đọc các khối lớn hơn có thể nhanh hơn:

< eightygigsfile.sql parallel --pipe --block 10M grep -i -C 5 'db_pd.Clients'

Câu hỏi của bạn không hoàn toàn rõ ràng, nhưng các tùy chọn khác grepbao gồm:

  • Làm rơi -icờ.
  • Sử dụng -Fcờ cho một chuỗi cố định
  • Tắt NLS với LANG=C
  • Đặt số lượng kết hợp tối đa với -mcờ.

2
Nếu đó là một tệp thực, hãy sử dụng --pipepartthay vì --pipe. Nó nhanh hơn nhiều.
Ole Tange

Việc sử dụng này không hỗ trợ mô hình bao gồm không gian, chúng ta cần phải sử dụng như thế này: song song --pipe --block 10M "/ usr / bin / grep -F -C5 -e 'Animal Care và vật nuôi"
zw963

<Ký tự đứng trước lệnh song song có nghĩa là gì?
elcortegano

1
@elcortegano: Đó là những gì được gọi là I / O chuyển hướng . Về cơ bản, nó đọc đầu vào từ tên tệp sau. Tương tự cat file.sql | parallel ...nhưng tránh UUOC . GNU song song cũng có một cách để đọc đầu vào từ một tập tin bằng cách sử dụng parallel ... :::: file.sql. HTH.
Steve

10

Một số cải tiến nhỏ:

  • Bỏ tùy chọn -i, nếu bạn có thể, phân biệt chữ hoa chữ thường khá chậm.

  • Thay thế .bởi\.

    Một điểm duy nhất là biểu tượng regex để khớp với bất kỳ ký tự nào, ký tự này cũng chậm


3

Hai dòng tấn công:

  • bạn có chắc chắn, bạn cần -i, hay bạn có khả năng loại bỏ nó?
  • Bạn có nhiều lõi hơn để chơi cùng không? greplà đơn luồng, vì vậy bạn có thể muốn bắt đầu thêm chúng ở các hiệu số khác nhau.

1
< eightygigsfile.sql parallel -k -j120% -n10 -m grep -F -i -C 5 'db_pd.Clients'  

Nếu bạn cần tìm kiếm nhiều chuỗi, tệp grep -f string.txt sẽ tiết kiệm rất nhiều thời gian. Trên đây là bản dịch của một cái gì đó mà tôi hiện đang thử nghiệm. giá trị tùy chọn -j và -n dường như hoạt động tốt nhất cho trường hợp sử dụng của tôi. Grep -F cũng tạo ra sự khác biệt lớn.

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.