Tích hợp tìm kiếm toàn văn cho ClickHouse bằng Quickwit Search Stream

Quickwit cung cấp tính năng Search Stream mạnh mẽ, cho phép truyền tải danh sách ID hoặc thuộc tính khớp với truy vấn tìm kiếm thông qua giao thức REST với tốc độ cực cao (lên tới 50 triệu bản ghi mỗi giây). ClickHouse có thể tận dụng luồng dữ liệu này để thực hiện các truy vấn JOIN, từ đó bổ sung khả năng tìm kiếm toàn văn (full-text search) vốn không phải là thế mạnh của các cơ sở dữ liệu OLAP truyền thống.

Trong hướng dẫn này, chúng ta sẽ sử dụng bộ dữ liệu GitHub Archive bao gồm hàng tỷ sự kiện như PullRequestEvent hay IssuesEvent để minh họa cách kết hợp hai công cụ này.

Cài đặt Quickwit

Đầu tiên, bạn cần tải và giải nén Quickwit trên hệ thống của mình:

curl -L https://install.quickwit.io | sh
cd quickwit-v*/

Khởi chạy dịch vụ Quickwit:

./quickwit run

Thiết lập Index trong Quickwit

Chúng ta cần định nghĩa một cấu hình index để lưu trữ các trường cần thiết cho việc tìm kiếm. Giả sử dữ liệu đầu vào có cấu trúc như sau:

{
  "id": 11410577343,
  "event_type": "PullRequestEvent",
  "actor_login": "developer_x",
  "repo_name": "org/repo",
  "created_at": 1580515200,
  "title": "Fix memory leak in worker",
  "body": "This PR addresses the issue reported in..."
}

Tạo file cấu hình gh-index-config.yaml. Lưu ý rằng chúng ta chỉ cần index các trường như titlebody để tìm kiếm, còn trường id sẽ được dùng để ánh xạ với ClickHouse.

version: 0.7
index_id: github-events-idx
doc_mapping:
  store_source: false
  field_mappings:
    - name: id
      type: u64
      fast: true
    - name: created_at
      type: datetime
      input_formats:
        - unix_timestamp
      output_format: unix_timestamp_secs
      fast: true
    - name: event_type
      type: text
      tokenizer: raw
    - name: title
      type: text
      tokenizer: default
      record: position
    - name: body
      type: text
      tokenizer: default
      record: position
  timestamp_field: created_at

search_settings:
  default_search_fields: [title, body]

Tiến hành tạo index bằng lệnh sau:

./quickwit index create --index-config gh-index-config.yaml

Nạp dữ liệu vào Quickwit

Sử dụng tập dữ liệu mẫu (dạng NDJSON nén) để nạp vào hệ thống:

wget https://quickwit-datasets-public.s3.amazonaws.com/gh-archive/gh-archive-2021-12-text-only.json.gz
gunzip -c gh-archive-2021-12-text-only.json.gz | ./quickwit index ingest --index github-events-idx

Bạn có thể kiểm tra dữ liệu đã vào hay chưa bằng một câu lệnh tìm kiếm đơn giản:

./quickwit index search --index github-events-idx --query "memory leak"

Cấu hình ClickHouse

Tiếp theo, chúng ta cần chuẩn bị bảng dữ liệu trong ClickHouse để lưu trữ thông tin chi tiết của các sự kiện GitHub.

CREATE DATABASE IF NOT EXISTS gh_analytics;
USE gh_analytics;

CREATE TABLE github_data
(
    id UInt64,
    event_type Enum('CommitCommentEvent' = 1, 'CreateEvent' = 2, 'DeleteEvent' = 3, 'ForkEvent' = 4,
                    'GollumEvent' = 5, 'IssueCommentEvent' = 6, 'IssuesEvent' = 7, 'MemberEvent' = 8,
                    'PublicEvent' = 9, 'PullRequestEvent' = 10, 'PullRequestReviewCommentEvent' = 11,
                    'PushEvent' = 12, 'ReleaseEvent' = 13, 'SponsorshipEvent' = 14, 'WatchEvent' = 15,
                    'GistEvent' = 16, 'FollowEvent' = 17, 'DownloadEvent' = 18, 'PullRequestReviewEvent' = 19,
                    'ForkApplyEvent' = 20, 'Event' = 21, 'TeamAddEvent' = 22),
    actor_login LowCardinality(String),
    repo_name LowCardinality(String),
    created_at Int64,
    action Enum('none' = 0, 'created' = 1, 'added' = 2, 'edited' = 3, 'deleted' = 4, 'opened' = 5, 'closed' = 6, 'reopened' = 7, 'assigned' = 8, 'unassigned' = 9,
                'labeled' = 10, 'unlabeled' = 11, 'review_requested' = 12, 'review_request_removed' = 13, 'synchronize' = 14, 'started' = 15, 'published' = 16, 'update' = 17, 'create' = 18, 'fork' = 19, 'merged' = 20),
    comment_id UInt64,
    body String,
    ref LowCardinality(String),
    number UInt32,
    title String,
    additions UInt32,
    deletions UInt32,
    commit_id String
) ENGINE = MergeTree ORDER BY (event_type, repo_name, created_at);

Nạp dữ liệu vào ClickHouse:

wget https://quickwit-datasets-public.s3.amazonaws.com/gh-archive/gh-archive-2021-12.json.gz
gunzip -c gh-archive-2021-12.json.gz | clickhouse-client -d gh_analytics --query="INSERT INTO github_data FORMAT JSONEachRow"

Sử dụng Search Stream để truy vấn

Sức mạnh thực sự nằm ở việc kết hợp URL table engine của ClickHouse với API của Quickwit. Chúng ta sẽ lấy danh sách ID từ Quickwit và dùng nó làm bộ lọc cho truy vấn trong ClickHouse.

Ví dụ: Tìm kiếm các sự kiện liên quan đến từ khóa "log4j" và thống kê theo ngày.

SELECT
    count(*) AS total_events,
    toDate(fromUnixTimestamp64Milli(created_at)) AS event_date
FROM github_data
WHERE id IN (
    SELECT id
    FROM url(
        'http://127.0.0.1:7280/api/v1/github-events-idx/search/stream?query=log4j&fast_field=id&output_format=click_house_row_binary', 
        RowBinary, 
        'id UInt64'
    )
)
GROUP BY event_date
ORDER BY event_date ASC;

Trong truy vấn trên:

  • Quickwit xử lý việc tìm kiếm toàn văn trên các trường text lớn và trả về luồng ID dưới định dạng RowBinary cực nhanh.
  • ClickHouse nhận luồng ID này và thực hiện phép lọc IN trên bảng github_data đã được tối ưu hóa cho phân tích.

Phương pháp này cho phép bạn tận dụng tốc độ xử lý dữ liệu lớn của ClickHouse mà vẫn có khả năng tìm kiếm linh hoạt của Quickwit mà không cần phải lưu trữ trùng lặp quá nhiều dữ liệu text trong ClickHouse.

Thẻ: ClickHouse Quickwit Full-Text Search olap Data Integration

Đăng vào ngày 20 tháng 6 lúc 23:52