PgGraph dia fampiasa amin'ny fitahirizana sy fitadiavana ny fiankinan-databatra ao amin'ny PostgreSQL

PgGraph dia fampiasa amin'ny fitahirizana sy fitadiavana ny fiankinan-databatra ao amin'ny PostgreSQL
Androany aho dia te-hanolotra ny mpamaky Habr miaraka amin'ny fitaovana voasoratra amin'ny Python ho an'ny fiasana amin'ny fiankinan-databatra ao amin'ny PostgreSQL DBMS.

Tsotra ny API an'ny utility ary misy fomba telo:

  • archive_table - fitahirizana/famafana andalana miverimberina miaraka amin'ny lakile fototra voatondro
  • get_table_references - mikaroka ireo fiankinan-doha amin'ny latabatra iray (hampiseho tabilao resahin'ilay voatondro sy ireo manondro azy)
  • get_rows_references - mitady andalana amin'ny tabilao hafa izay manondro andalana voafaritra ao amin'ny latabatra tiana

prehistory

Oleg Borzov no anarako, mpamorona ao amin'ny ekipa CRM ho an'ny mpitantana fampindramam-bola any Domklik aho.

Ny angon-drakitra fototra amin'ny rafitra CRM dia iray amin'ireo lehibe indrindra amin'ny resaka volume ao amin'ny orinasa. Iray amin'ireo tranainy indrindra ihany koa izy io: niseho tamin'ny fanombohan'ny tetikasa, rehefa lehibe ny hazo, Domklik dia fanombohana, ary raha tokony ho microservice amin'ny rafitra Python asynchronous lamaody dia nisy monolith goavana tao amin'ny PHP.

Naharitra ela ny fifindrana avy amin'ny PHP mankany Python ary nitaky fanohanana nifanandrify tamin'ireo rafitra roa ireo, izay nisy fiantraikany tamin'ny famolavolana ny angon-drakitra.

Vokatr'izany dia manana angon-drakitra misy tabilao marobe mifandray sy lehibe miaraka amin'ny tondro maromaro ho an'ny karazana fanontaniana samihafa. Izany rehetra izany dia misy fiantraikany ratsy amin'ny fahombiazan'ny angon-drakitra: noho ny latabatra lehibe sy ny fifamatorana misy eo amin'izy ireo, dia mitombo hatrany ny fahasarotan'ny fanontaniana, izay tena manan-danja indrindra ho an'ny latabatra be entana indrindra.

Mba hampihenana ny enta-mavesatra ao amin'ny angon-drakitra, dia nanapa-kevitra ny hanoratra script izay hamindra rakitra taloha avy amin'ny latabatra be dia be sy feno entana mankany amin'ny tahiry (ohatra, avy amin'ny task Π² task_archive).

Sarotra ity asa ity noho ny hamaroan'ny fifandraisana eo amin'ny latabatra: esory fotsiny ny andalana avy task Π² task_archive dia tsy ampy, alohan'izay dia mila manao toy izany koa ianao amin'ireo referansa rehetra task latabatra.

Hampiseho ohatra aho angon-drakitra demo avy amin'ny tranokala postgrespro.ru:

PgGraph dia fampiasa amin'ny fitahirizana sy fitadiavana ny fiankinan-databatra ao amin'ny PostgreSQL
Andeha hatao hoe mila mamafa rakitra amin'ny latabatra isika Flights. Tsy avelan'ny Postgres hanao an'izany sahala amin'izany isika: mila mamafa ny firaketana amin'ny tabilao fanondroana rehetra aloha isika, ary toy izany hatrany midina any amin'ny tabilao tsy misy olona resahina.

Amin'ny ohatra ataontsika amin'ny Flights milaza Ticket_flights, ary momba azy- Boarding_passes.

Noho izany dia mila mamafa azy amin'ity filaharana ity ianao:

  1. Mahazo ny soatoavin'ny laharana voalohany (PK) izahay Ticket_flights, izay manondro ireo andalana hofafana ao Flights.
  2. Mahazo laharana PK izahay Boarding_passes, izay manondro Ticket_flights.
  3. Esory ny andalana amin'ny PK amin'ny dingana 2 amin'ny latabatra Boarding_passes.
  4. Fafao ny andalana amin'ny PK amin'ny dingana 1 in Ticket_flights.
  5. Esory ny tsipika avy amin'ny Flights.

Ny vokatra dia fitaovana iray antsoina hoe PgGraph, izay nanapa-kevitra ny hanao loharano misokatra.

Ahoana ny fampiasana

Ny utility dia manohana fomba fampiasana roa:

  • Antso avy amin'ny andalana baiko (pggraph …).
  • Fampiasana amin'ny code Python (class PgGraphApi).

Fametrahana sy fikirakirana

Voalohany dia mila mametraka ny utility avy amin'ny tahiry Pypi ianao:

pip3 install pggraph

Avy eo dia mamorona rakitra config.ini amin'ny milina eo an-toerana miaraka amin'ny fanamafisana ny angon-drakitra sy ny script archiving:

[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'

MialΓ  amin'ny console

masontsivana

$ 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)

Tohan-kevitra momba ny toerana:

  • action - fepetra takiana: archive_table, get_table_references na get_rows_references.

Hevitra nomena:

  • --config_path - lalana mankany amin'ny rakitra config;
  • --table - latabatra izay ilainao hanaovana hetsika;
  • --ids - lisitry ny id misaraka amin'ny faingo, ohatra, 1,2,3 (famaritana azo atao);
  • --log_path - lalana mankany amin'ny lahatahiry ho an'ny log (parameter azo atao, amin'ny alΓ lan'ny default - lahatahiry an-trano);
  • --log_level - haavon'ny logging (parameter azo atao, INFO ny default).

Ohatra baiko

Mitahiry latabatra

Ny tena fiasan'ny utility dia ny fitahirizana angon-drakitra, i.e. mamindra andalana avy amin'ny latabatra lehibe mankany amin'ny latabatra arisiva (ohatra, avy amin'ny latabatra boky Π² books_archive).

Ny famafana tsy misy arisiva dia tohana ihany koa: noho izany dia mila mametraka ny parameter ao amin'ny config.ini ianao to_archive = diso).

Paramètre ilaina - config_path, latabatra ary id.

Aorian'ny fandefasana dia ho voafafa miverimberina ny rakitra ids eo amin'ny latabatra table ary eo amin'ny latabatra rehetra izay ilazana azy.

$ 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

Mitadiava fiankinana ho an'ny latabatra voafaritra

Asa hitadiavana fiankinan'ny latabatra voafaritra table. Paramètre ilaina - config_path и table.

Aorian'ny fandefasana dia hisy rakibolana hiseho eo amin'ny efijery, izay ahitana:

  • in_refs - rakibolana misy tabilao manondro iray nomena, izay ny lakile dia ny anaran'ny latabatra, ny sanda dia lisitry ny zavatra Foreign Key (pk_main - lakile voalohany amin'ny latabatra lehibe, pk_ref - lakile voalohany eo amin'ny latabatra fanondroana, fk_ref - ny anaran'ny tsanganana izay fanalahidy vahiny amin'ny latabatra loharano);
  • out_refs β€” rakibolana misy tabilao resahin'ity iray ity.

$ 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')]}}

Mitady fanondroana tady miaraka amin'ny lakile Kilonga voatondro

Miasa hikaroka andalana amin'ny tabilao hafa izay manondro andalana amin'ny alalan'ny Foreign Key ids latabatra table. Paramètre ilaina - config_path, table и ids.

Aorian'ny fandefasana dia hiseho eo amin'ny efijery ny rakibolana misy ity rafitra manaraka ity:

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

Ohatra antso:

$ 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'}]}}}

Fampiasana amin'ny code

Ankoatra ny fampandehanana azy ao amin'ny console, ny tranomboky dia azo ampiasaina amin'ny code Python. Ohatra amin'ny antso ao amin'ny tontolo iPython interactive dia aseho eto ambany.

Mitahiry latabatra

>>> 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

Mitadiava fiankinana ho an'ny latabatra voafaritra

>>> 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')]}}

Mitady fanondroana tady miaraka amin'ny lakile Kilonga voatondro

>>> 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'}]}}}

Ny kaody loharanon'ny tranomboky dia hita ao amin'ny GitHub eo ambanin'ny lisansa MIT, ary koa ao amin'ny tahiry PyPI.

Ho faly aho haneho hevitra, fanoloran-tena ary soso-kevitra.

Hiezaka aho hamaly fanontaniana araka izay azoko atao eto sy ao amin'ny tahiry.

Source: www.habr.com

Add a comment