PgGraph په PostgreSQL کې د میز انحصارونو د آرشیف کولو او موندلو لپاره یو کار دی

PgGraph په PostgreSQL کې د میز انحصارونو د آرشیف کولو او موندلو لپاره یو کار دی
نن زه غواړم د هابر لوستونکو ته د PostgreSQL DBMS کې د میز انحصارونو سره کار کولو لپاره په Python کې لیکل شوي یوټیلټي وړاندې کړم.

د کارونې API ساده دی او درې میتودونه لري:

  • آرشیف_میز - د ټاکل شوي لومړني کیلي سره تکراري آرشیف / قطارونه حذف کول
  • ترلاسه کړئ جدول_حواله - د جدول لپاره د انحصارونو لټون وکړئ (د ټاکل شوي یو لخوا حواله شوي میزونه به وښیې او هغه څوک چې ورته اشاره کوي)
  • ترلاسه_کړي_حوال - په نورو جدولونو کې د قطارونو لټون وکړئ چې په مطلوب جدول کې مشخص شوي قطارونو ته اشاره کوي

له تاریخ څخه دمخه

زما نوم اولیګ بورزوف دی، زه په ډومکلیک کې د ګروي پور ورکولو مدیرانو لپاره د CRM ټیم کې پراختیا کونکی یم.

زموږ د CRM سیسټم اصلي ډیټابیس په شرکت کې د حجم له مخې ترټولو لوی دی. دا یو له پخوانیو څخه هم دی: دا د پروژې په پیل کې څرګند شو ، کله چې ونې لویې وې ، ډومکلیک یو پیل و ، او د فیشني پیتون غیر متمرکز چوکاټ کې د مایکرو سرویس پرځای په پی ایچ پی کې یو لوی مونولیت شتون درلود.

د پی ایچ پی څخه پیتون ته لیږد خورا اوږد و او د دواړو سیسټمونو یوځل ملاتړ ته اړتیا وه ، کوم چې د ډیټابیس ډیزاین اغیزه کړې.

د پایلې په توګه، موږ یو ډیټابیس لرو چې د ډیری ډیری ډیری تړل شوي او لوی میزونو سره د مختلفو ډولونو پوښتنو لپاره د شاخصونو یو ګروپ سره. دا ټول د ډیټابیس فعالیت باندې منفي اغیزه کوي: د لوی جدولونو او د دوی ترمینځ د اړیکو د یوې ډلې له امله ، د پوښتنو پیچلتیا په دوامداره توګه وده کوي ، کوم چې په ځانګړي توګه د ډیری بار شوي میزونو لپاره خورا مهم دی.

په ډیټابیس کې د بار کمولو لپاره، موږ پریکړه وکړه چې یو سکریپټ ولیکئ چې زاړه ریکارډونه به له خورا لوی او بار شوي جدولونو څخه آرشیف ته انتقال کړي (د مثال په توګه، له task в task_archive).

دا دنده د جدولونو تر مینځ د ډیرو اړیکو له امله پیچلې ده: په ساده ډول له قطارونو څخه حرکت وکړئ task в task_archive کافي نه ده، مخکې لدې چې تاسو اړتیا لرئ د ټولو هغو حوالو سره په تکرار سره ورته کار وکړئ task میزونه

زه به د یو مثال سره څرګند کړم د ډیمو ډیټابیس د سایټ postgrespro.ru څخه:

PgGraph په PostgreSQL کې د میز انحصارونو د آرشیف کولو او موندلو لپاره یو کار دی
راځئ چې ووایو موږ اړتیا لرو ریکارډونه له میز څخه حذف کړو Flights. پوسټګریس به موږ ته اجازه ورنکړي چې دا په ورته ډول ترسره کړو: موږ لومړی اړتیا لرو د ټولو حوالې میزونو څخه ریکارډونه حذف کړو ، او همداسې په تکراري ډول میزونو ته چې د هیچا لخوا راجع شوي ندي.

زموږ په مثال کې Flights حواله کوي Ticket_flights، او د هغې په اړه - Boarding_passes.

له همدې امله، تاسو باید دا په دې ترتیب کې حذف کړئ:

  1. موږ د قطارونو لومړني کیلي (PK) ارزښتونه ترلاسه کوو Ticket_flights، کوم چې د حذف کولو لپاره قطارونو ته اشاره کوي Flights.
  2. موږ د PK قطارونه ترلاسه کوو Boarding_passes، کوم چې مراجعه کوي Ticket_flights.
  3. موږ په جدول کې د 2 مرحلې څخه د PK لخوا قطارونه حذف کوو Boarding_passes.
  4. د 1 مرحلې څخه د PK لخوا لینونه حذف کړئ Ticket_flights.
  5. د کرښو لرې کول Flights.

پایله د PgGraph په نوم یو ګټورتیا وه، کوم چې موږ پریکړه وکړه چې خلاص سرچینه جوړه کړو.

څنګه کارول کیږي

یوټیلیټ د کارولو دوه طریقې ملاتړ کوي:

  • د کمانډ لاین څخه زنګ ووهئ (pggraph …).
  • په Python کوډ کې کارول (ټولګي PgGraphApi).

نصب او ترتیب

لومړی تاسو اړتیا لرئ د Pypi ذخیره څخه یوټیلټي نصب کړئ:

pip3 install pggraph

بیا د ډیټابیس ترتیب او آرشیف سکریپټ سره په محلي ماشین کې د config.ini فایل رامینځته کړئ:

[db]
host = localhost
port = 5432
user = postgres
password = postgres
dbname = postgres
schema = public ; Необязательный параметр, указано значение по умолчанию

[archive]  ; Данный раздел заполнять необязательно, ниже указаны значения по умолчанию
is_debug = false
chunk_size = 1000
max_depth = 20
to_archive = true
archive_suffix = 'archive'

د کنسول څخه چلول

پارامترونو

$ pggraph -h
usage: pggraph action [-h] --table TABLE [--ids IDS] [--config_path CONFIG_PATH]
positional arguments:
  action        required action: archive_table, get_table_references, get_rows_references

optional arguments:
  -h, --help                    show this help message and exit
  --table TABLE                 table name
  --ids IDS                     primary key ids, separated by comma, e.g. 1,2,3
  --config_path CONFIG_PATH     path to config.ini
  --log_path LOG_PATH           path to log dir
  --log_level LOG_LEVEL         log level (debug, info, error)

موقفي دلیلونه:

  • action - اړین اقدام: archive_table, get_table_references او یا get_rows_references.

نومول شوي دلیلونه:

  • --config_path - د تشکیل فایل ته لاره؛
  • --table - یو میز چې تاسو ورته اړتیا لرئ یو عمل ترسره کړئ؛
  • --ids - د کوما لخوا جلا شوي ID لیست، د بیلګې په توګه، 1,2,3 (اختیاري پیرامیټر)؛
  • --log_path - د لاګونو لپاره فولډر ته لاره (اختیاري پیرامیټر، په ډیفالټ - کور فولډر)؛
  • --log_level - د ننوتلو کچه (اختیاري پیرامیټر، ډیفالټ INFO دی).

د قوماندې مثالونه

د میز آرشیف کول

د کارونې اصلي دنده د معلوماتو آرشیف کول دي، د بیلګې په توګه. د اصلي میز څخه آرشیف میز ته د قطارونو لیږد (د مثال په توګه، د میز څخه کتابونه в book_archive).

د آرشیف پرته حذف کول هم ملاتړ کیږي: د دې لپاره تاسو اړتیا لرئ په config.ini کې پیرامیټر تنظیم کړئ to_archive = غلط).

اړین پیرامیټونه - config_path، جدول او ids.

د پیل کولو وروسته، ریکارډونه به په تکراري توګه حذف شي ids په میز کې table او په ټولو جدولونو کې چې ورته اشاره کوي.

$ pggraph archive_table --config_path config.hw.local.ini --table flights --ids 1,2,3
2020-06-20 19:27:44 INFO: flights - START
2020-06-20 19:27:44 INFO: flights - start archive_recursive 3 rows (depth=0)
2020-06-20 19:27:44 INFO:       START ARCHIVE REFERRING TABLES
2020-06-20 19:27:44 INFO:       ticket_flights - start archive_recursive 3 rows (depth=1)
2020-06-20 19:27:44 INFO:               START ARCHIVE REFERRING TABLES
2020-06-20 19:27:44 INFO:               boarding_passes - start archive_recursive 3 rows (depth=2)
2020-06-20 19:27:44 INFO:                       START ARCHIVE REFERRING TABLES
2020-06-20 19:27:44 INFO:                       END ARCHIVE REFERRING TABLES
2020-06-20 19:27:44 INFO:               boarding_passes - archive_by_ids 3 rows by ticket_no, flight_id
2020-06-20 19:27:44 INFO:               boarding_passes - start archive_recursive 3 rows (depth=2)
2020-06-20 19:27:44 INFO:                       START ARCHIVE REFERRING TABLES
2020-06-20 19:27:44 INFO:                       END ARCHIVE REFERRING TABLES
2020-06-20 19:27:44 INFO:               boarding_passes - archive_by_ids 3 rows by ticket_no, flight_id
2020-06-20 19:27:44 INFO:               boarding_passes - start archive_recursive 3 rows (depth=2)
2020-06-20 19:27:44 INFO:                       START ARCHIVE REFERRING TABLES
2020-06-20 19:27:44 INFO:                       END ARCHIVE REFERRING TABLES
2020-06-20 19:27:44 INFO:               boarding_passes - archive_by_ids 3 rows by ticket_no, flight_id
2020-06-20 19:27:44 INFO:               boarding_passes - start archive_recursive 3 rows (depth=2)
2020-06-20 19:27:44 INFO:                       START ARCHIVE REFERRING TABLES
2020-06-20 19:27:44 INFO:                       END ARCHIVE REFERRING TABLES
2020-06-20 19:27:44 INFO:               boarding_passes - archive_by_ids 3 rows by ticket_no, flight_id
2020-06-20 19:27:44 INFO:               END ARCHIVE REFERRING TABLES
2020-06-20 19:27:44 INFO:       ticket_flights - archive_by_ids 3 rows by ticket_no, flight_id
2020-06-20 19:27:44 INFO:       END ARCHIVE REFERRING TABLES
2020-06-20 19:27:44 INFO: flights - archive_by_ids 3 rows by id
2020-06-20 19:27:44 INFO: flights - END

د ټاکل شوي میز لپاره انحصار ومومئ

د ټاکل شوي جدول د انحصار موندلو دنده table. اړین پیرامیټونه - config_path и table.

د پیل کولو وروسته، یو قاموس به په سکرین کې ښکاره شي، چیرته چې:

  • in_refs - د جدولونو یوه قاموس چې ورکړل شوي ته اشاره کوي، چیرې چې کیلي د میز نوم دی، ارزښت د بهرنیو کلیدي شیانو لیست دی (pk_main - په اصلي جدول کې لومړنۍ کیلي، pk_ref - د حوالې په جدول کې لومړنۍ کیلي، fk_ref - د کالم نوم چې د سرچینې جدول ته بهرنۍ کیلي ده؛
  • out_refs - د جدولونو قاموس چې دا ورته اشاره کوي.

$ pggraph get_table_references --config_path config.hw.local.ini --table flights
{'in_refs': {'ticket_flights': [ForeignKey(pk_main='flight_id', pk_ref='ticket_no, flight_id', fk_ref='flight_id')]},
 'out_refs': {'aircrafts': [ForeignKey(pk_main='aircraft_code', pk_ref='flight_id', fk_ref='aircraft_code')],
              'airports': [ForeignKey(pk_main='airport_code', pk_ref='flight_id', fk_ref='arrival_airport'),
                           ForeignKey(pk_main='airport_code', pk_ref='flight_id', fk_ref='departure_airport')]}}

د ټاکل شوي لومړني کیلي سره تارونو ته د حوالې موندل

په نورو جدولونو کې د قطارونو لټون کولو فنکشن چې د بهرني کیلي له لارې قطارونو ته اشاره کوي ids میزونه table. اړین پیرامیټونه - config_path, table и ids.

د پیل کولو وروسته، د لاندې جوړښت سره یو قاموس به په سکرین کې ښکاره شي:

{
	pk_id_1: {
		reffering_table_name_1: {
			foreign_key_1: [
				{row_pk_1: value, row_pk_2: value},
				...
			], 
			...
		},
		...
	},
	pk_id_2: {...},
	...
}

بیلګه تلیفون:

$ pggraph get_rows_references --config_path config.hw.local.ini --table flights --ids 1,2,3
{1: {'ticket_flights': {'flight_id': [{'flight_id': 1,
                                       'ticket_no': '0005432816945'},
                                      {'flight_id': 1,
                                       'ticket_no': '0005432816941'}]}},
 2: {'ticket_flights': {'flight_id': [{'flight_id': 2,
                                       'ticket_no': '0005433101832'},
                                      {'flight_id': 2,
                                       'ticket_no': '0005433101864'},
                                      {'flight_id': 2,
                                       'ticket_no': '0005432919715'}]}},
 3: {'ticket_flights': {'flight_id': [{'flight_id': 3,
                                       'ticket_no': '0005432817560'},
                                      {'flight_id': 3,
                                       'ticket_no': '0005432817568'},
                                      {'flight_id': 3,
                                       'ticket_no': '0005432817559'}]}}}

په کوډ کې کارول

په کنسول کې د چلولو سربیره، کتابتون د Python کوډ کې کارول کیدی شي. د iPython متقابل چاپیریال کې د زنګونو مثالونه لاندې ښودل شوي.

د میز آرشیف کول

>>> from pg_graph.main import setup_logging
>>> setup_logging(log_level='DEBUG')
>>> from pg_graph.api import PgGraphApi
>>> api = PgGraphApi('config.hw.local.ini')
>>> api.archive_table('flights', [4,5])
2020-06-20 23:12:08 INFO: flights - START
2020-06-20 23:12:08 INFO: flights - start archive_recursive 2 rows (depth=0)
2020-06-20 23:12:08 INFO: 	START ARCHIVE REFERRING TABLES
2020-06-20 23:12:08 DEBUG: 	ticket_flights - ForeignKey(pk_main='flight_id', pk_ref='flight_id, ticket_no', fk_ref='flight_id')
2020-06-20 23:12:08 DEBUG: 	SQL('SELECT flight_id, ticket_no FROM bookings.ticket_flights WHERE (flight_id) IN (%s, %s)')
2020-06-20 23:12:08 INFO: 	ticket_flights - start archive_recursive 30 rows (depth=1)
2020-06-20 23:12:08 INFO: 		START ARCHIVE REFERRING TABLES
2020-06-20 23:12:08 DEBUG: 		boarding_passes - ForeignKey(pk_main='flight_id, ticket_no', pk_ref='flight_id, ticket_no', fk_ref='flight_id, ticket_no')
2020-06-20 23:12:08 INFO: 		boarding_passes - archive_by_fk 30 rows by ForeignKey(pk_main='flight_id, ticket_no', pk_ref='flight_id, ticket_no', fk_ref='flight_id, ticket_no')
2020-06-20 23:12:08 DEBUG: 		SQL('CREATE TABLE IF NOT EXISTS bookings.boarding_passes_archive (LIKE bookings.boarding_passes)')
2020-06-20 23:12:08 DEBUG: 		DELETE FROM boarding_passes by FK flight_id, ticket_no - 30 rows
2020-06-20 23:12:08 INFO: 		END ARCHIVE REFERRING TABLES
2020-06-20 23:12:08 INFO: 	ticket_flights - archive_by_ids 30 rows by flight_id, ticket_no
2020-06-20 23:12:08 DEBUG: 	SQL('CREATE TABLE IF NOT EXISTS bookings.ticket_flights_archive (LIKE bookings.ticket_flights)')
2020-06-20 23:12:08 DEBUG: 	DELETE FROM ticket_flights by flight_id, ticket_no - 30 rows
2020-06-20 23:12:08 DEBUG: 	INSERT INTO ticket_flights_archive - 30 rows
2020-06-20 23:12:08 INFO: 	ticket_flights - start archive_recursive 30 rows (depth=1)
2020-06-20 23:12:08 INFO: 		START ARCHIVE REFERRING TABLES
2020-06-20 23:12:08 DEBUG: 		boarding_passes - ForeignKey(pk_main='flight_id, ticket_no', pk_ref='flight_id, ticket_no', fk_ref='flight_id, ticket_no')
2020-06-20 23:12:08 INFO: 		boarding_passes - archive_by_fk 30 rows by ForeignKey(pk_main='flight_id, ticket_no', pk_ref='flight_id, ticket_no', fk_ref='flight_id, ticket_no')
2020-06-20 23:12:08 DEBUG: 		SQL('CREATE TABLE IF NOT EXISTS bookings.boarding_passes_archive (LIKE bookings.boarding_passes)')
2020-06-20 23:12:08 DEBUG: 		DELETE FROM boarding_passes by FK flight_id, ticket_no - 30 rows
2020-06-20 23:12:08 INFO: 		END ARCHIVE REFERRING TABLES
2020-06-20 23:12:08 INFO: 	ticket_flights - archive_by_ids 30 rows by flight_id, ticket_no
2020-06-20 23:12:08 DEBUG: 	SQL('CREATE TABLE IF NOT EXISTS bookings.ticket_flights_archive (LIKE bookings.ticket_flights)')
2020-06-20 23:12:08 DEBUG: 	DELETE FROM ticket_flights by flight_id, ticket_no - 30 rows
2020-06-20 23:12:08 DEBUG: 	INSERT INTO ticket_flights_archive - 30 rows
2020-06-20 23:12:08 INFO: 	ticket_flights - start archive_recursive 30 rows (depth=1)
2020-06-20 23:12:08 INFO: 		START ARCHIVE REFERRING TABLES
2020-06-20 23:12:08 DEBUG: 		boarding_passes - ForeignKey(pk_main='flight_id, ticket_no', pk_ref='flight_id, ticket_no', fk_ref='flight_id, ticket_no')
2020-06-20 23:12:08 INFO: 		boarding_passes - archive_by_fk 30 rows by ForeignKey(pk_main='flight_id, ticket_no', pk_ref='flight_id, ticket_no', fk_ref='flight_id, ticket_no')
2020-06-20 23:12:08 DEBUG: 		SQL('CREATE TABLE IF NOT EXISTS bookings.boarding_passes_archive (LIKE bookings.boarding_passes)')
2020-06-20 23:12:08 DEBUG: 		DELETE FROM boarding_passes by FK flight_id, ticket_no - 30 rows
2020-06-20 23:12:08 INFO: 		END ARCHIVE REFERRING TABLES
2020-06-20 23:12:08 INFO: 	ticket_flights - archive_by_ids 30 rows by flight_id, ticket_no
2020-06-20 23:12:08 DEBUG: 	SQL('CREATE TABLE IF NOT EXISTS bookings.ticket_flights_archive (LIKE bookings.ticket_flights)')
2020-06-20 23:12:08 DEBUG: 	DELETE FROM ticket_flights by flight_id, ticket_no - 30 rows
2020-06-20 23:12:08 DEBUG: 	INSERT INTO ticket_flights_archive - 30 rows
2020-06-20 23:12:08 INFO: 	ticket_flights - start archive_recursive 3 rows (depth=1)
2020-06-20 23:12:08 INFO: 		START ARCHIVE REFERRING TABLES
2020-06-20 23:12:08 DEBUG: 		boarding_passes - ForeignKey(pk_main='flight_id, ticket_no', pk_ref='flight_id, ticket_no', fk_ref='flight_id, ticket_no')
2020-06-20 23:12:08 INFO: 		boarding_passes - archive_by_fk 3 rows by ForeignKey(pk_main='flight_id, ticket_no', pk_ref='flight_id, ticket_no', fk_ref='flight_id, ticket_no')
2020-06-20 23:12:08 DEBUG: 		SQL('CREATE TABLE IF NOT EXISTS bookings.boarding_passes_archive (LIKE bookings.boarding_passes)')
2020-06-20 23:12:08 DEBUG: 		DELETE FROM boarding_passes by FK flight_id, ticket_no - 3 rows
2020-06-20 23:12:08 INFO: 		END ARCHIVE REFERRING TABLES
2020-06-20 23:12:08 INFO: 	ticket_flights - archive_by_ids 3 rows by flight_id, ticket_no
2020-06-20 23:12:08 DEBUG: 	SQL('CREATE TABLE IF NOT EXISTS bookings.ticket_flights_archive (LIKE bookings.ticket_flights)')
2020-06-20 23:12:08 DEBUG: 	DELETE FROM ticket_flights by flight_id, ticket_no - 3 rows
2020-06-20 23:12:08 DEBUG: 	INSERT INTO ticket_flights_archive - 3 rows
2020-06-20 23:12:08 INFO: 	END ARCHIVE REFERRING TABLES
2020-06-20 23:12:08 INFO: flights - archive_by_ids 2 rows by flight_id
2020-06-20 23:12:09 DEBUG: SQL('CREATE TABLE IF NOT EXISTS bookings.flights_archive (LIKE bookings.flights)')
2020-06-20 23:12:09 DEBUG: DELETE FROM flights by flight_id - 2 rows
2020-06-20 23:12:09 DEBUG: INSERT INTO flights_archive - 2 rows
2020-06-20 23:12:09 INFO: flights - END

د ټاکل شوي میز لپاره انحصار ومومئ

>>> from pg_graph.api import PgGraphApi
>>> from pprint import pprint
>>> api = PgGraphApi('config.hw.local.ini')
>>> res = api.get_table_references('flights')
>>> pprint(res)
{'in_refs': {'ticket_flights': [ForeignKey(pk_main='flight_id', pk_ref='flight_id, ticket_no', fk_ref='flight_id')]},
 'out_refs': {'aircrafts': [ForeignKey(pk_main='aircraft_code', pk_ref='flight_id', fk_ref='aircraft_code')],
              'airports': [ForeignKey(pk_main='airport_code', pk_ref='flight_id', fk_ref='arrival_airport'),
                           ForeignKey(pk_main='airport_code', pk_ref='flight_id', fk_ref='departure_airport')]}}

د ټاکل شوي لومړني کیلي سره تارونو ته د حوالې موندل

>>> from pg_graph.api import PgGraphApi
>>> from pprint import pprint
>>> api = PgGraphApi('config.hw.local.ini')
>>> rows = api.get_rows_references('flights', [1,2,3])
>>> pprint(rows)
{1: {'ticket_flights': {'flight_id': [{'flight_id': 1,
                                       'ticket_no': '0005432816945'},
                                      {'flight_id': 1,
                                       'ticket_no': '0005432816941'}]}},
 2: {'ticket_flights': {'flight_id': [{'flight_id': 2,
                                       'ticket_no': '0005433101832'},
                                      {'flight_id': 2,
                                       'ticket_no': '0005433101864'},
                                      {'flight_id': 2,
                                       'ticket_no': '0005432919715'}]}},
 3: {'ticket_flights': {'flight_id': [{'flight_id': 3,
                                       'ticket_no': '0005432817560'},
                                      {'flight_id': 3,
                                       'ticket_no': '0005432817568'},
                                      {'flight_id': 3,
                                       'ticket_no': '0005432817559'}]}}}

د کتابتون د سرچینې کوډ په کې شتون لري GitHub د MIT جواز لاندې، او همدارنګه په ذخیره کې PyPI.

زه به د نظرونو، ژمنو او وړاندیزونو څخه خوښ شم.

زه به هڅه وکړم چې دلته او په ذخیره کې زما د وړتیا څخه غوره پوښتنو ته ځواب ووایم.

سرچینه: www.habr.com

Add a comment