Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Khối lượng công việc kết hợp cơ sở dữ liệu OLTP / Analytics:Sao chép dữ liệu MySQL sang ClickHouse

Làm cách nào để chạy Analytics trên MySQL?

MySQL là một cơ sở dữ liệu tuyệt vời cho khối lượng công việc Xử lý Giao dịch Trực tuyến (OLTP). Đối với một số công ty, nó đã từng là quá đủ trong một thời gian dài. Thời đại đã thay đổi và các yêu cầu kinh doanh cùng với chúng. Khi các doanh nghiệp mong muốn hướng đến dữ liệu nhiều hơn, ngày càng nhiều dữ liệu được lưu trữ để phân tích sâu hơn; hành vi của khách hàng, các mẫu hiệu suất, lưu lượng mạng, nhật ký, v.v. Bất kể bạn làm trong ngành nào, rất có thể có dữ liệu mà bạn muốn lưu giữ và phân tích để hiểu rõ hơn về những gì đang diễn ra và cách cải thiện hoạt động kinh doanh của mình. Thật không may, để lưu trữ và truy vấn một lượng lớn dữ liệu, MySQL không phải là lựa chọn tốt nhất. Chắc chắn, nó có thể làm được và nó có các công cụ để giúp chứa một lượng lớn dữ liệu (ví dụ:nén InnoDB), nhưng việc sử dụng một giải pháp chuyên dụng cho Xử lý phân tích trực tuyến (OLAP) rất có thể sẽ cải thiện đáng kể khả năng lưu trữ và truy vấn một số lượng lớn của bạn dữ liệu.

Một cách để giải quyết vấn đề này là sử dụng cơ sở dữ liệu chuyên dụng để chạy phân tích. Thông thường, bạn muốn sử dụng kho dữ liệu dạng cột cho các tác vụ như vậy - chúng phù hợp hơn để xử lý số lượng lớn dữ liệu:dữ liệu được lưu trữ trong các cột thường dễ nén hơn, cũng dễ truy cập hơn trên cơ sở mỗi cột - thông thường bạn yêu cầu một số dữ liệu được lưu trữ trong một vài cột - khả năng chỉ truy xuất các cột đó thay vì đọc tất cả các hàng và lọc ra dữ liệu không cần thiết giúp dữ liệu được truy cập nhanh hơn.

Làm cách nào để sao chép dữ liệu từ MySQL sang ClickHouse?

Một ví dụ về kho dữ liệu dạng cột phù hợp cho phân tích là ClickHouse, một cửa hàng cột mã nguồn mở. Một thách thức là đảm bảo dữ liệu trong ClickHouse đồng bộ với dữ liệu trong MySQL. Chắc chắn, luôn có thể thiết lập một đường dẫn dữ liệu theo một số loại và thực hiện tải hàng loạt tự động vào ClickHouse. Nhưng miễn là bạn có thể sống với một số hạn chế, có một cách tốt hơn để thiết lập sao chép gần như thời gian thực từ MySQL vào ClickHouse. Trong bài đăng trên blog này, chúng tôi sẽ xem xét cách nó có thể được thực hiện.

Cài đặt ClickHouse

Trước hết, chúng ta cần cài đặt ClickHouse. Chúng tôi sẽ sử dụng phần khởi động nhanh từ trang web ClickHouse.

sudo apt-get install dirmngr    # optional
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv E0C56BD4    # optional

echo "deb http://repo.yandex.ru/clickhouse/deb/stable/ main/" | sudo tee /etc/apt/sources.list.d/clickhouse.list
sudo apt-get update
sudo apt-get install -y clickhouse-server clickhouse-client
sudo service clickhouse-server start

Khi điều này được thực hiện, chúng ta cần tìm một phương tiện để chuyển dữ liệu từ MySQL vào ClickHouse. Một trong những giải pháp khả thi là sử dụng clickhouse-mysql-data-reader của Altinity. Trước hết, chúng ta phải cài đặt pip3 (python3-pip trong Ubuntu) vì Python trong phiên bản ít nhất là 3.4 là bắt buộc. Sau đó, chúng tôi có thể sử dụng pip3 để cài đặt một số mô-đun Python được yêu cầu:

pip3 install mysqlclient
pip3 install mysql-replication
pip3 install clickhouse-driver

Khi điều này được thực hiện, chúng tôi phải sao chép kho lưu trữ. Đối với Centos 7, RPM cũng có sẵn, cũng có thể cài đặt nó bằng cách sử dụng pip3 (gói clickhouse-mysql) nhưng chúng tôi nhận thấy rằng phiên bản có sẵn thông qua pip không chứa các bản cập nhật mới nhất và chúng tôi muốn sử dụng nhánh chính từ kho lưu trữ git:

git clone https://github.com/Altinity/clickhouse-mysql-data-reader

Sau đó, chúng ta có thể cài đặt nó bằng cách sử dụng pip:

pip3 install -e /path/to/clickhouse-mysql-data-reader/

Bước tiếp theo sẽ là tạo người dùng MySQL theo yêu cầu của clickhouse-mysql-data-reader để truy cập dữ liệu MySQL:

mysql> CREATE USER 'chreader'@'%' IDENTIFIED BY 'pass';
Query OK, 0 rows affected (0.02 sec)
mysql> CREATE USER 'chreader'@'127.0.0.1' IDENTIFIED BY 'pass';
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE USER 'chreader'@'localhost' IDENTIFIED BY 'pass';
Query OK, 0 rows affected (0.02 sec)
mysql> GRANT SELECT, REPLICATION CLIENT, REPLICATION SLAVE, SUPER ON *.* TO 'chreader'@'%';
Query OK, 0 rows affected (0.01 sec)
mysql> GRANT SELECT, REPLICATION CLIENT, REPLICATION SLAVE, SUPER ON *.* TO 'chreader'@'127.0.0.1';
Query OK, 0 rows affected (0.00 sec)
mysql> GRANT SELECT, REPLICATION CLIENT, REPLICATION SLAVE, SUPER ON *.* TO 'chreader'@'localhost';
Query OK, 0 rows affected, 1 warning (0.01 sec)

Bạn cũng nên xem lại cấu hình MySQL của mình để đảm bảo rằng bạn đã bật nhật ký nhị phân, max_binlog_size được đặt thành 768M, binlog ở định dạng ‘hàng’ và công cụ có thể kết nối với MySQL. Dưới đây là phần trích dẫn từ tài liệu:

[mysqld]
# mandatory
server-id        = 1
log_bin          = /var/lib/mysql/bin.log
binlog-format    = row # very important if you want to receive write, update and delete row events
# optional
expire_logs_days = 30
max_binlog_size  = 768M
# setup listen address
bind-address     = 0.0.0.0

Nhập dữ liệu

Khi mọi thứ đã sẵn sàng, bạn có thể nhập dữ liệu vào ClickHouse. Tốt nhất là bạn nên chạy quá trình nhập trên một máy chủ có các bảng bị khóa để không có thay đổi nào xảy ra trong quá trình này. Bạn có thể sử dụng một nô lệ làm nguồn dữ liệu. Lệnh chạy sẽ là:

clickhouse-mysql --src-server-id=1 --src-wait --nice-pause=1 --src-host=10.0.0.142 --src-user=chreader --src-password=pass --src-tables=wiki.pageviews --dst-host=127.0.0.1 --dst-create-table --migrate-table

Nó sẽ kết nối với MySQL trên máy chủ 10.0.0.142 bằng cách sử dụng thông tin xác thực đã cho, nó sẽ sao chép bảng ‘pageviews’ trong lược đồ ‘wiki’ vào một ClickHouse chạy trên máy chủ cục bộ (127.0.0.1). Bảng sẽ được tạo tự động và dữ liệu sẽ được di chuyển.

Với mục đích của blog này, chúng tôi đã nhập khoảng 50 triệu hàng từ tập dữ liệu “số lần xem trang” do Wikimedia Foundation cung cấp. Lược đồ bảng trong MySQL là:

mysql> SHOW CREATE TABLE wiki.pageviews\G
*************************** 1. row ***************************
       Table: pageviews
Create Table: CREATE TABLE `pageviews` (
  `date` date NOT NULL,
  `hour` tinyint(4) NOT NULL,
  `code` varbinary(255) NOT NULL,
  `title` varbinary(1000) NOT NULL,
  `monthly` bigint(20) DEFAULT NULL,
  `hourly` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`date`,`hour`,`code`,`title`)
) ENGINE=InnoDB DEFAULT CHARSET=binary
1 row in set (0.00 sec)

Công cụ đã dịch điều này thành giản đồ ClickHouse sau:

vagrant.vm :) SHOW CREATE TABLE wiki.pageviews\G

SHOW CREATE TABLE wiki.pageviews

Row 1:
──────
statement: CREATE TABLE wiki.pageviews ( date Date,  hour Int8,  code String,  title String,  monthly Nullable(Int64),  hourly Nullable(Int64)) ENGINE = MergeTree(date, (date, hour, code, title), 8192)

1 rows in set. Elapsed: 0.060 sec.

Sau khi nhập xong, chúng ta có thể so sánh nội dung của MySQL:

mysql> SELECT COUNT(*) FROM wiki.pageviews\G
*************************** 1. row ***************************
COUNT(*): 50986914
1 row in set (24.56 sec)

và trong ClickHouse:

vagrant.vm :) SELECT COUNT(*) FROM wiki.pageviews\G

SELECT COUNT(*)
FROM wiki.pageviews

Row 1:
──────
COUNT(): 50986914

1 rows in set. Elapsed: 0.014 sec. Processed 50.99 million rows, 50.99 MB (3.60 billion rows/s., 3.60 GB/s.)

Ngay cả trong một bảng nhỏ như vậy, bạn có thể thấy rõ rằng MySQL cần nhiều thời gian hơn để quét qua nó so với ClickHouse.

Khi bắt đầu quá trình xem nhật ký nhị phân cho các sự kiện, lý tưởng nhất là bạn nên chuyển thông tin về tệp nhật ký nhị phân và vị trí từ nơi công cụ sẽ bắt đầu lắng nghe. Bạn có thể dễ dàng kiểm tra điều đó trên máy nô lệ sau khi quá trình nhập lần đầu hoàn tất.

clickhouse-mysql --src-server-id=1 --src-resume --src-binlog-file='binlog.000016' --src-binlog-position=194 --src-wait --nice-pause=1 --src-host=10.0.0.142 --src-user=chreader --src-password=pass --src-tables=wiki.pageviews --dst-host=127.0.0.1 --pump-data --csvpool

Nếu bạn không vượt qua nó, nó sẽ chỉ bắt đầu lắng nghe bất cứ điều gì đến:

clickhouse-mysql --src-server-id=1 --src-resume --src-wait --nice-pause=1 --src-host=10.0.0.142 --src-user=chreader --src-password=pass --src-tables=wiki.pageviews --dst-host=127.0.0.1 --pump-data --csvpool

Hãy tải thêm một số dữ liệu và xem nó sẽ hoạt động như thế nào đối với chúng tôi. Chúng ta có thể thấy rằng mọi thứ có vẻ ổn bằng cách xem nhật ký của clickhouse-mysql-data-reader:

2019-02-11 15:21:29,705/1549898489.705732:INFO:['wiki.pageviews']
2019-02-11 15:21:29,706/1549898489.706199:DEBUG:class:<class 'clickhouse_mysql.writer.poolwriter.PoolWriter'> insert
2019-02-11 15:21:29,706/1549898489.706682:DEBUG:Next event binlog pos: binlog.000016.42066434
2019-02-11 15:21:29,707/1549898489.707067:DEBUG:WriteRowsEvent #224892 rows: 1
2019-02-11 15:21:29,707/1549898489.707483:INFO:['wiki.pageviews']
2019-02-11 15:21:29,707/1549898489.707899:DEBUG:class:<class 'clickhouse_mysql.writer.poolwriter.PoolWriter'> insert
2019-02-11 15:21:29,708/1549898489.708083:DEBUG:Next event binlog pos: binlog.000016.42066595
2019-02-11 15:21:29,708/1549898489.708659:DEBUG:WriteRowsEvent #224893 rows: 1

Những gì chúng ta phải ghi nhớ là những hạn chế của công cụ. Điểm lớn nhất là nó chỉ hỗ trợ INSERT. Không hỗ trợ DELETE hoặc UPDATE. Cũng không có hỗ trợ cho DDL, do đó bất kỳ thay đổi lược đồ không tương thích nào được thực thi trên MySQL sẽ phá vỡ bản sao MySQL thành ClickHouse.

Cũng đáng chú ý là thực tế là các nhà phát triển của tập lệnh khuyến nghị sử dụng pypy để cải thiện hiệu suất của công cụ. Hãy thực hiện một số bước cần thiết để thiết lập điều này.

Lúc đầu, bạn phải tải xuống và giải nén pypy:

wget https://bitbucket.org/squeaky/portable-pypy/downloads/pypy3.5-7.0.0-linux_x86_64-portable.tar.bz2
tar jxf pypy3.5-7.0.0-linux_x86_64-portable.tar.bz2
cd pypy3.5-7.0.0-linux_x86_64-portable

Tiếp theo, chúng ta phải cài đặt pip và tất cả các yêu cầu cho clickhouse-mysql-data-reader - giống hệt như những thứ chúng ta đã đề cập trước đó, trong khi mô tả thiết lập thông thường:

./bin/pypy -m ensurepip
./bin/pip3 install mysql-replication
./bin/pip3 install clickhouse-driver
./bin/pip3 install mysqlclient

Bước cuối cùng sẽ là cài đặt clickhouse-mysql-data-reader từ kho lưu trữ github (chúng tôi cho rằng nó đã được nhân bản):

./bin/pip3 install -e /path/to/clickhouse-mysql-data-reader/

Đó là tất cả. Bắt đầu từ bây giờ, bạn nên chạy tất cả các lệnh bằng cách sử dụng môi trường được tạo cho pypy:

./bin/pypy ./bin/clickhouse-mysql

Kiểm tra

Dữ liệu đã được tải, chúng tôi có thể xác minh rằng mọi thứ diễn ra suôn sẻ bằng cách so sánh kích thước của bảng:

MySQL:

mysql> SELECT COUNT(*) FROM wiki.pageviews\G
*************************** 1. row ***************************
COUNT(*): 204899465
1 row in set (1 min 40.12 sec)

ClickHouse:

vagrant.vm :) SELECT COUNT(*) FROM wiki.pageviews\G

SELECT COUNT(*)
FROM wiki.pageviews

Row 1:
──────
COUNT(): 204899465

1 rows in set. Elapsed: 0.100 sec. Processed 204.90 million rows, 204.90 MB (2.04 billion rows/s., 2.04 GB/s.)

Mọi thứ có vẻ chính xác. Hãy chạy một số truy vấn để xem ClickHouse hoạt động như thế nào. Xin lưu ý rằng tất cả thiết lập này khác xa với cấp sản xuất. Chúng tôi đã sử dụng hai máy ảo nhỏ, bộ nhớ 4GB, mỗi máy một vCPU. Do đó, mặc dù tập dữ liệu không lớn nhưng cũng đủ để thấy sự khác biệt. Do mẫu nhỏ nên khá khó để thực hiện phân tích "thực" nhưng chúng tôi vẫn có thể đưa ra một số truy vấn ngẫu nhiên.

Hãy kiểm tra xem chúng tôi có dữ liệu từ những ngày nào trong tuần và số lượng trang đã được xem mỗi ngày trong dữ liệu mẫu của chúng tôi:

vagrant.vm :) SELECT count(*), toDayOfWeek(date) AS day FROM wiki.pageviews GROUP BY day ORDER BY day ASC;

SELECT
    count(*),
    toDayOfWeek(date) AS day
FROM wiki.pageviews
GROUP BY day
ORDER BY day ASC

┌───count()─┬─day─┐
│  50986896 │   2 │
│ 153912569 │   3 │
└───────────┴─────┘

2 rows in set. Elapsed: 2.457 sec. Processed 204.90 million rows, 409.80 MB (83.41 million rows/s., 166.82 MB/s.)

Trong trường hợp của MySQL, truy vấn này trông giống như dưới đây:

mysql> SELECT COUNT(*), DAYOFWEEK(date) AS day FROM wiki.pageviews GROUP BY day ORDER BY day;
+-----------+------+
| COUNT(*)  | day  |
+-----------+------+
|  50986896 |    3 |
| 153912569 |    4 |
+-----------+------+
2 rows in set (3 min 35.88 sec)

Như bạn thấy, MySQL cần 3,5 phút để quét toàn bộ bảng.

Bây giờ, hãy xem có bao nhiêu trang có giá trị hàng tháng lớn hơn 100:

vagrant.vm :) SELECT count(*), toDayOfWeek(date) AS day FROM wiki.pageviews WHERE  monthly > 100 GROUP BY day;

SELECT
    count(*),
    toDayOfWeek(date) AS day
FROM wiki.pageviews
WHERE monthly > 100
GROUP BY day

┌─count()─┬─day─┐
│   83574 │   2 │
│  246237 │   3 │
└─────────┴─────┘

2 rows in set. Elapsed: 1.362 sec. Processed 204.90 million rows, 1.84 GB (150.41 million rows/s., 1.35 GB/s.)

Trong trường hợp của MySQL, thời gian lặp lại là 3,5 phút:

mysql> SELECT COUNT(*), DAYOFWEEK(date) AS day FROM wiki.pageviews WHERE YEAR(date) = 2018 AND monthly > 100 GROUP BY day;
^@^@+----------+------+
| COUNT(*) | day  |
+----------+------+
|    83574 |    3 |
|   246237 |    4 |
+----------+------+
2 rows in set (3 min 3.48 sec)

Một truy vấn khác, chỉ là tra cứu dựa trên một số giá trị chuỗi:

vagrant.vm :) select * from wiki.pageviews where title LIKE 'Main_Page' AND code LIKE 'de.m' AND hour=6;

SELECT *
FROM wiki.pageviews
WHERE (title LIKE 'Main_Page') AND (code LIKE 'de.m') AND (hour = 6)

┌───────date─┬─hour─┬─code─┬─title─────┬─monthly─┬─hourly─┐
│ 2018-05-01 │    6 │ de.m │ Main_Page │       8 │      0 │
└────────────┴──────┴──────┴───────────┴─────────┴────────┘
┌───────date─┬─hour─┬─code─┬─title─────┬─monthly─┬─hourly─┐
│ 2018-05-02 │    6 │ de.m │ Main_Page │      17 │      0 │
└────────────┴──────┴──────┴───────────┴─────────┴────────┘

2 rows in set. Elapsed: 0.015 sec. Processed 66.70 thousand rows, 4.20 MB (4.48 million rows/s., 281.53 MB/s.)

Một truy vấn khác, thực hiện một số tra cứu trong chuỗi và một điều kiện dựa trên cột "hàng tháng":

vagrant.vm :) select title from wiki.pageviews where title LIKE 'United%Nations%' AND code LIKE 'en.m' AND monthly>100 group by title;

SELECT title
FROM wiki.pageviews
WHERE (title LIKE 'United%Nations%') AND (code LIKE 'en.m') AND (monthly > 100)
GROUP BY title

┌─title───────────────────────────┐
│ United_Nations                  │
│ United_Nations_Security_Council │
└─────────────────────────────────┘

2 rows in set. Elapsed: 0.083 sec. Processed 1.61 million rows, 14.62 MB (19.37 million rows/s., 175.34 MB/s.)

Trong trường hợp của MySQL, nó trông như sau:

mysql> SELECT * FROM wiki.pageviews WHERE title LIKE 'Main_Page' AND code LIKE 'de.m' AND hour=6;
+------------+------+------+-----------+---------+--------+
| date       | hour | code | title     | monthly | hourly |
+------------+------+------+-----------+---------+--------+
| 2018-05-01 |    6 | de.m | Main_Page |       8 |      0 |
| 2018-05-02 |    6 | de.m | Main_Page |      17 |      0 |
+------------+------+------+-----------+---------+--------+
2 rows in set (2 min 45.83 sec)

Vì vậy, gần 3 phút. Truy vấn thứ hai giống nhau:

mysql> select title from wiki.pageviews where title LIKE 'United%Nations%' AND code LIKE 'en.m' AND monthly>100 group by title;
+---------------------------------+
| title                           |
+---------------------------------+
| United_Nations                  |
| United_Nations_Security_Council |
+---------------------------------+
2 rows in set (2 min 40.91 sec)

Tất nhiên, người ta có thể lập luận rằng bạn có thể thêm nhiều chỉ mục hơn để cải thiện hiệu suất truy vấn, nhưng thực tế là, việc thêm chỉ mục sẽ yêu cầu thêm dữ liệu được lưu trữ trên đĩa. Các chỉ mục yêu cầu không gian đĩa và chúng cũng đặt ra những thách thức về hoạt động - nếu chúng ta đang nói về tập dữ liệu OLAP trong thế giới thực, chúng ta đang nói về terabyte dữ liệu. Để chạy các thay đổi lược đồ trên môi trường như vậy, cần rất nhiều thời gian và yêu cầu một quy trình được xác định và kiểm tra rõ ràng. Đây là lý do tại sao các kho dữ liệu dạng cột chuyên dụng có thể rất tiện dụng và giúp ích rất nhiều để có được cái nhìn sâu sắc hơn về tất cả dữ liệu phân tích mà mọi người lưu trữ.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Chiến lược sao lưu và phục hồi MySQL / MariaDB thành công

  2. PDO + MySQL và mã hóa UTF-8 bị hỏng

  3. Làm thế nào để có được số lượng của mỗi giá trị khác nhau trong một cột?

  4. PHP &MySQL:mysqli_num_rows () mong muốn tham số 1 là mysqli_result, boolean đã cho

  5. Sử dụng Bí danh trong Tính toán SQL