MySQL पर Analytics कैसे चलाएं?
MySQL ऑनलाइन ट्रांजेक्शन प्रोसेसिंग (OLTP) वर्कलोड के लिए एक बेहतरीन डेटाबेस है। कुछ कंपनियों के लिए, यह लंबे समय तक पर्याप्त से अधिक हुआ करता था। समय बदल गया है और उनके साथ-साथ व्यावसायिक आवश्यकताएं भी। जैसा कि व्यवसाय अधिक डेटा-चालित होने की इच्छा रखते हैं, अधिक से अधिक डेटा को आगे के विश्लेषण के लिए संग्रहीत किया जाता है; ग्राहक व्यवहार, प्रदर्शन पैटर्न, नेटवर्क ट्रैफ़िक, लॉग आदि। कोई फर्क नहीं पड़ता कि आप किस उद्योग में हैं, यह बहुत संभावना है कि डेटा है जिसे आप बेहतर ढंग से समझने के लिए रखना और विश्लेषण करना चाहते हैं कि क्या हो रहा है और अपने व्यवसाय को कैसे सुधारें। दुर्भाग्य से, बड़ी मात्रा में डेटा संग्रहीत करने और क्वेरी करने के लिए, MySQL सबसे अच्छा विकल्प नहीं है। निश्चित रूप से, यह यह कर सकता है और इसमें बड़ी मात्रा में डेटा (जैसे, InnoDB संपीड़न) को समायोजित करने में मदद करने के लिए उपकरण हैं, लेकिन ऑनलाइन एनालिटिक्स प्रोसेसिंग (OLAP) के लिए एक समर्पित समाधान का उपयोग करने से सबसे अधिक संभावना है कि बड़ी मात्रा में स्टोर और क्वेरी करने की आपकी क्षमता में सुधार होगा। डेटा का।
इस समस्या से निपटने का एक तरीका एनालिटिक्स चलाने के लिए एक समर्पित डेटाबेस का उपयोग करना होगा। आम तौर पर, आप ऐसे कार्यों के लिए कॉलमर डेटास्टोर का उपयोग करना चाहते हैं - वे बड़ी मात्रा में डेटा को संभालने के लिए अधिक उपयुक्त हैं:कॉलम में संग्रहीत डेटा आमतौर पर संपीड़ित करना आसान होता है, प्रति कॉलम आधार पर पहुंचना भी आसान होता है - आम तौर पर आप कुछ मांगते हैं कुछ स्तंभों में संग्रहीत डेटा - सभी पंक्तियों को पढ़ने और अनावश्यक डेटा को फ़िल्टर करने के बजाय केवल उन स्तंभों को पुनः प्राप्त करने की क्षमता से डेटा तक तेज़ी से पहुँचा जा सकता है।
MySQL से ClickHouse में डेटा कैसे रिपीट करें?
कॉलमर डेटास्टोर का एक उदाहरण जो एनालिटिक्स के लिए उपयुक्त है, क्लिकहाउस, एक ओपन सोर्स कॉलम स्टोर है। एक चुनौती यह सुनिश्चित करना है कि क्लिकहाउस में डेटा MySQL में डेटा के साथ समन्वयित है। निश्चित रूप से, किसी प्रकार की डेटा पाइपलाइन सेट करना और क्लिकहाउस में स्वचालित बैच लोडिंग करना हमेशा संभव होता है। लेकिन जब तक आप कुछ सीमाओं के साथ रह सकते हैं, तब तक MySQL से क्लिकहाउस में लगभग रीयल-टाइम प्रतिकृति स्थापित करने का एक बेहतर तरीका है। इस ब्लॉग पोस्ट में हम देखेंगे कि यह कैसे किया जा सकता है।
क्लिकहाउस इंस्टॉलेशन
सबसे पहले हमें 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
एक बार यह हो जाने के बाद, हमें डेटा को MySQL से ClickHouse में स्थानांतरित करने के लिए एक साधन खोजने की आवश्यकता है। संभावित समाधानों में से एक है Altinity के क्लिकहाउस-mysql-डेटा-रीडर का उपयोग करना। सबसे पहले, हमें pip3 (उबंटू में पाइथॉन 3-पाइप) स्थापित करना होगा क्योंकि कम से कम 3.4 संस्करण में पायथन की आवश्यकता है। फिर हम कुछ आवश्यक पायथन मॉड्यूल स्थापित करने के लिए pip3 का उपयोग कर सकते हैं:
pip3 install mysqlclient
pip3 install mysql-replication
pip3 install clickhouse-driver
एक बार यह हो जाने के बाद, हमें रिपॉजिटरी को क्लोन करना होगा। Centos 7 के लिए, RPM भी उपलब्ध हैं, इसे pip3 (क्लिकहाउस-mysql पैकेज) का उपयोग करके स्थापित करना भी संभव है, लेकिन हमने पाया कि पाइप के माध्यम से उपलब्ध संस्करण में नवीनतम अपडेट नहीं हैं और हम git रिपॉजिटरी से मास्टर शाखा का उपयोग करना चाहते हैं:
git clone https://github.com/Altinity/clickhouse-mysql-data-reader
फिर, हम इसे पाइप का उपयोग करके स्थापित कर सकते हैं:
pip3 install -e /path/to/clickhouse-mysql-data-reader/
अगला कदम MySQL डेटा तक पहुँचने के लिए क्लिकहाउस-mysql-डेटा-रीडर द्वारा आवश्यक 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)
आपको यह सुनिश्चित करने के लिए अपने MySQL कॉन्फ़िगरेशन की समीक्षा करनी चाहिए कि आपके पास बाइनरी लॉग सक्षम हैं, max_binlog_size 768M पर सेट है, बिनलॉग 'पंक्ति' प्रारूप में हैं और यह टूल MySQL से कनेक्ट हो सकता है। नीचे दस्तावेज़ीकरण का एक अंश दिया गया है:
[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
डेटा आयात करना
जब सब कुछ तैयार हो जाए तो आप डेटा को क्लिकहाउस में आयात कर सकते हैं। आदर्श रूप से आप एक मेजबान पर टेबल लॉक के साथ आयात चलाएंगे ताकि प्रक्रिया के दौरान कोई बदलाव न हो। आप डेटा के स्रोत के रूप में दास का उपयोग कर सकते हैं। चलाने का आदेश होगा:
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
यह दिए गए क्रेडेंशियल्स का उपयोग करके होस्ट 10.0.0.142 पर MySQL से कनेक्ट होगा, यह स्थानीय होस्ट (127.0.0.1) पर चल रहे एक क्लिकहाउस में स्कीमा 'विकी' में तालिका 'पेजव्यू' की प्रतिलिपि बनाएगा। तालिका स्वचालित रूप से बनाई जाएगी और डेटा माइग्रेट किया जाएगा।
इस ब्लॉग के उद्देश्य के लिए हमने विकिमीडिया फाउंडेशन द्वारा उपलब्ध कराए गए "पेजव्यू" डेटासेट से लगभग 50 मिलियन पंक्तियों को आयात किया है। MySQL में टेबल स्कीमा है:
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)
टूल ने इसे निम्नलिखित क्लिकहाउस स्कीमा में अनुवादित किया:
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.
एक बार आयात हो जाने के बाद, हम MySQL की सामग्री की तुलना कर सकते हैं:
mysql> SELECT COUNT(*) FROM wiki.pageviews\G
*************************** 1. row ***************************
COUNT(*): 50986914
1 row in set (24.56 sec)
और क्लिकहाउस में:
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.)
इतनी छोटी तालिका में भी आप स्पष्ट रूप से देख सकते हैं कि MySQL को इसे स्कैन करने के लिए ClickHouse की तुलना में अधिक समय की आवश्यकता है।
घटनाओं के लिए बाइनरी लॉग देखने की प्रक्रिया शुरू करते समय, आदर्श रूप से आप बाइनरी लॉग फ़ाइल और उस स्थिति के बारे में जानकारी पास करेंगे जहां से टूल को सुनना शुरू करना चाहिए। आरंभिक आयात पूरा होने के बाद आप इसे आसानी से स्लेव पर देख सकते हैं।
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
यदि आप इसे पास नहीं करते हैं, तो यह इसमें आने वाली किसी भी चीज़ को सुनना शुरू कर देगा:
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
आइए कुछ और डेटा लोड करें और देखें कि यह हमारे लिए कैसे काम करेगा। क्लिकहाउस-mysql-डेटा-रीडर के लॉग को देखकर हम देख सकते हैं कि सब कुछ ठीक लगता है:
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
हमें जो ध्यान में रखना है वह उपकरण की सीमाएं हैं। सबसे बड़ी बात यह है कि यह INSERTs को ही सपोर्ट करता है। DELETE या UPDATE के लिए कोई समर्थन नहीं है। डीडीएल के लिए भी कोई समर्थन नहीं है इसलिए MySQL पर निष्पादित कोई भी असंगत स्कीमा परिवर्तन MySQL को क्लिकहाउस प्रतिकृति में तोड़ देगा।
यह भी ध्यान देने योग्य है कि स्क्रिप्ट के डेवलपर्स टूल के प्रदर्शन को बेहतर बनाने के लिए pypy का उपयोग करने की सलाह देते हैं। आइए इसे सेट अप करने के लिए आवश्यक कुछ चरणों के बारे में जानते हैं।
सबसे पहले आपको 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
इसके बाद, हमें क्लिकहाउस-mysql-डेटा-रीडर के लिए पाइप और सभी आवश्यकताओं को स्थापित करना होगा - ठीक वही चीजें जिन्हें हमने पहले कवर किया था, जबकि नियमित सेटअप का वर्णन करते हुए:
./bin/pypy -m ensurepip
./bin/pip3 install mysql-replication
./bin/pip3 install clickhouse-driver
./bin/pip3 install mysqlclient
अंतिम चरण जीथब रिपोजिटरी से क्लिकहाउस-माइस्क्ल-डेटा-रीडर स्थापित करना होगा (हम मानते हैं कि इसे पहले ही क्लोन किया जा चुका है):
./bin/pip3 install -e /path/to/clickhouse-mysql-data-reader/
बस इतना ही। अभी से आपको pypy के लिए बनाए गए वातावरण का उपयोग करके सभी कमांड चलानी चाहिए:
./bin/pypy ./bin/clickhouse-mysql
परीक्षा
डेटा लोड कर दिया गया है, हम तालिका के आकार की तुलना करके सत्यापित कर सकते हैं कि सब कुछ सुचारू रूप से चला गया:
MySQL:
mysql> SELECT COUNT(*) FROM wiki.pageviews\G
*************************** 1. row ***************************
COUNT(*): 204899465
1 row in set (1 min 40.12 sec)
क्लिकहाउस:
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.)
सब कुछ सही दिखता है। क्लिकहाउस कैसे व्यवहार करता है, यह देखने के लिए आइए कुछ प्रश्नों को चलाएं। कृपया ध्यान रखें कि यह सभी सेटअप प्रोडक्शन-ग्रेड से बहुत दूर है। हमने दो छोटे VM, 4GB मेमोरी, प्रत्येक में एक vCPU का उपयोग किया। इसलिए भले ही डेटासेट बड़ा नहीं था, लेकिन यह अंतर देखने के लिए पर्याप्त था। छोटे नमूने के कारण "वास्तविक" विश्लेषण करना काफी कठिन है, लेकिन हम अभी भी कुछ यादृच्छिक प्रश्नों को फेंक सकते हैं।
आइए देखें कि हमारे पास सप्ताह के किन दिनों का डेटा है और हमारे नमूना डेटा में प्रति दिन कितने पृष्ठ देखे गए हैं:
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.)
MySQL के मामले में यह क्वेरी नीचे की तरह दिखती है:
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)
जैसा कि आप देख सकते हैं, MySQL को एक पूर्ण तालिका स्कैन करने के लिए 3.5 मिनट की आवश्यकता है।
अब, देखते हैं कि कितने पृष्ठों का मासिक मूल्य 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.)
MySQL के मामले में यह फिर से 3.5 मिनट है:
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)
एक और क्वेरी, कुछ स्ट्रिंग मानों के आधार पर बस एक लुकअप:
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.)
एक अन्य क्वेरी, स्ट्रिंग में कुछ लुकअप करना और 'मासिक' कॉलम पर आधारित एक शर्त:
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.)
MySQL के मामले में यह नीचे जैसा दिखता है:
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)
तो, लगभग 3 मिनट। दूसरी क्वेरी वही है:
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)
बेशक, कोई यह तर्क दे सकता है कि आप क्वेरी प्रदर्शन को बेहतर बनाने के लिए अधिक अनुक्रमणिका जोड़ सकते हैं, लेकिन तथ्य यह है कि अनुक्रमणिका को जोड़ने के लिए डिस्क पर संग्रहीत करने के लिए अतिरिक्त डेटा की आवश्यकता होगी। इंडेक्स को डिस्क स्थान की आवश्यकता होती है और वे परिचालन चुनौतियों का भी सामना करते हैं - अगर हम वास्तविक दुनिया के OLAP डेटा सेट के बारे में बात कर रहे हैं, तो हम डेटा के टेराबाइट्स के बारे में बात कर रहे हैं। इसमें बहुत समय लगता है और ऐसे वातावरण पर स्कीमा परिवर्तन चलाने के लिए एक अच्छी तरह से परिभाषित और परीक्षण प्रक्रिया की आवश्यकता होती है। यही कारण है कि समर्पित कॉलमर डेटास्टोर बहुत आसान हो सकते हैं और सभी एनालिटिक्स डेटा में बेहतर अंतर्दृष्टि प्राप्त करने में काफी मदद कर सकते हैं जो हर कोई स्टोर करता है।