mirror of
https://github.com/sandronator/finetuning_aufgabe4.git
synced 2026-09-04 08:36:09 +02:00
The Manager previously called setupBoth() on every test step, which dropped both PostgreSQL and MariaDB tables and re-imported the full DBLP TSVs (~9 reloads across 2 DBs in a single run, even though only PostgreSQL was used). Now data is loaded once via load_data_postgres() and only the indexes are swapped between tests via apply_indexes_postgres(). A reset_postgres(config, reload_data=False) helper lets callers force a full reload when needed -- used after 'cl-both' tests, since CLUSTER physically reorders the table and dropping the index alone does not restore the original layout. Also fixes two bugs found while reading the code: - baseStrategy.run iterated 'self.queries' instead of '.items()', which would crash on the first unpack. - main.py was missing an execute() call after the Aufgabe 3 'cl-both' setup, silently skipping that test. Co-Authored-By: Claude Opus 4.7 <[email protected]>
234 lines
6.6 KiB
Python
234 lines
6.6 KiB
Python
import mariadb
|
|
import psycopg2
|
|
import time
|
|
import os
|
|
import argparse
|
|
from dotenv import load_dotenv
|
|
|
|
load_dotenv()
|
|
|
|
COUNT_AUTH_ENTRIES_QUERY = "SELECT COUNT(*) FROM auth"
|
|
COUNT_PUBL_ENTRIES_QUERY = "SELECT COUNT(*) FROM publ"
|
|
|
|
INDEX_CONFIGS = {
|
|
"no-index": [],
|
|
"unique-publ": [
|
|
"CREATE UNIQUE INDEX publ_pubid_idx ON publ(pubid);",
|
|
],
|
|
"nc-publ": [
|
|
"CREATE INDEX publ_pubid_idx ON publ(pubid);",
|
|
],
|
|
"nc-auth": [
|
|
"CREATE INDEX auth_pubid_idx ON auth(pubid);",
|
|
],
|
|
"nc-both": [
|
|
"CREATE INDEX publ_pubid_idx ON publ(pubid);",
|
|
"CREATE INDEX auth_pubid_idx ON auth(pubid);",
|
|
],
|
|
"cl-both": [
|
|
"CREATE INDEX publ_pubid_idx ON publ(pubid);",
|
|
"CLUSTER publ USING publ_pubid_idx;",
|
|
"CREATE INDEX auth_pubid_idx ON auth(pubid);",
|
|
"CLUSTER auth USING auth_pubid_idx;",
|
|
],
|
|
}
|
|
|
|
|
|
KNOWN_INDEX_NAMES = ("publ_pubid_idx", "auth_pubid_idx")
|
|
|
|
|
|
def load_data_postgres():
|
|
"""Drops and re-creates auth/publ in PostgreSQL and bulk-loads the TSV files.
|
|
|
|
Call this once at the start of a run, then use apply_indexes_postgres
|
|
between tests instead of reloading the whole dataset.
|
|
"""
|
|
_, connection = get_connection(maria=False)
|
|
cursor = connection.cursor()
|
|
|
|
_create_tables_force(cursor)
|
|
|
|
start = time.time()
|
|
|
|
file_auth = open(f"{os.getenv('PATH_AUTH')}", "r", encoding="utf-8")
|
|
file_publ = open(f"{os.getenv('PATH_PUBL')}", "r", encoding="utf-8")
|
|
|
|
cursor.copy_from(file_auth, "auth", sep="\t", columns=("name", "pubid"))
|
|
cursor.copy_from(
|
|
file_publ,
|
|
"publ",
|
|
sep="\t",
|
|
columns=("pubid", "type", "title", "booktitle", "year", "publisher"),
|
|
)
|
|
|
|
connection.commit()
|
|
end = time.time()
|
|
|
|
cursor.execute(COUNT_AUTH_ENTRIES_QUERY)
|
|
auth_entries = cursor.fetchall()[0][0]
|
|
cursor.execute(COUNT_PUBL_ENTRIES_QUERY)
|
|
publ_entries = cursor.fetchall()[0][0]
|
|
|
|
print(f"Entries Auth: {auth_entries}")
|
|
print(f"Entries Publ: {publ_entries}")
|
|
print(f"Total Entries (Auth, Publ): {auth_entries + publ_entries}")
|
|
print(f"PostgreSQL Load Runtime: {end - start:.2f} seconds")
|
|
|
|
cursor.close()
|
|
connection.close()
|
|
|
|
|
|
def apply_indexes_postgres(index_config):
|
|
"""Drops all known indexes and applies the given index configuration.
|
|
|
|
Note: CLUSTER physically reorders the table. Dropping the index afterwards
|
|
does NOT undo that ordering. If a test needs the original physical order
|
|
after a previous 'cl-both' run, call load_data_postgres() again.
|
|
"""
|
|
_, connection = get_connection(maria=False)
|
|
cursor = connection.cursor()
|
|
|
|
for idx_name in KNOWN_INDEX_NAMES:
|
|
cursor.execute(f"DROP INDEX IF EXISTS {idx_name};")
|
|
|
|
for command in INDEX_CONFIGS[index_config]:
|
|
print("Applying:", command)
|
|
cursor.execute(command)
|
|
|
|
connection.commit()
|
|
cursor.close()
|
|
connection.close()
|
|
|
|
|
|
def reset_postgres(index_config, reload_data=False):
|
|
"""Bring PostgreSQL into the desired state for the next test.
|
|
|
|
Set reload_data=True when the previous test clustered the table and the
|
|
next test needs a non-clustered physical layout.
|
|
"""
|
|
if reload_data:
|
|
load_data_postgres()
|
|
apply_indexes_postgres(index_config)
|
|
|
|
|
|
def create_distribute_postgres(index_config):
|
|
"""Legacy: full reload + index setup in PostgreSQL. Kept for the CLI."""
|
|
load_data_postgres()
|
|
apply_indexes_postgres(index_config)
|
|
|
|
|
|
def create_distribute_maria(index_config):
|
|
_ ,connection = get_connection(maria=True)
|
|
cursor = connection.cursor()
|
|
_create_tables_force(cursor)
|
|
|
|
start = time.time()
|
|
|
|
cursor.execute(f"""
|
|
LOAD DATA LOCAL INFILE '{os.getenv("PATH_AUTH")}'
|
|
INTO TABLE auth
|
|
FIELDS TERMINATED BY '\\t'
|
|
LINES TERMINATED BY '\\n'
|
|
(name, pubid)
|
|
""")
|
|
|
|
cursor.execute(f"""
|
|
LOAD DATA LOCAL INFILE '{os.getenv("PATH_PUBL")}'
|
|
INTO TABLE publ
|
|
FIELDS TERMINATED BY '\\t'
|
|
LINES TERMINATED BY '\\n'
|
|
(pubid, type, title, booktitle, year, publisher)
|
|
""")
|
|
|
|
connection.commit()
|
|
end = time.time()
|
|
|
|
print("MariaDB Runtime:", end - start, "seconds")
|
|
|
|
for command in INDEX_CONFIGS[index_config]:
|
|
if command.startswith("CLUSTER"):
|
|
print("Skipping (not supported in MariaDB):", command)
|
|
continue
|
|
print("Applying:", command)
|
|
cursor.execute(command)
|
|
connection.commit()
|
|
|
|
cursor.execute(COUNT_AUTH_ENTRIES_QUERY)
|
|
entries = cursor.fetchall()[0][0]
|
|
print("Entries Auth: " + str(entries))
|
|
cursor.execute(COUNT_PUBL_ENTRIES_QUERY)
|
|
publ_entries = cursor.fetchall()[0][0]
|
|
print("Entries Publ: " + str(publ_entries))
|
|
entries += publ_entries
|
|
|
|
print("Total Entries (Auth, Publ): " + str(entries))
|
|
|
|
cursor.close()
|
|
connection.close()
|
|
|
|
|
|
def get_connection(maria: bool) -> tuple[str, mariadb.Connection | psycopg2.extensions.connection]:
|
|
connection = None
|
|
db_name = "None"
|
|
if not maria:
|
|
connection = psycopg2.connect(
|
|
dbname=os.getenv("POSTGRES_DB"),
|
|
user=os.getenv("POSTGRES_USER"),
|
|
password=os.getenv("POSTGRES_PASS"),
|
|
host="localhost",
|
|
port="5432",
|
|
)
|
|
db_name = "postgresql"
|
|
|
|
else:
|
|
connection = mariadb.connect(
|
|
user=os.getenv("MARIA_USER"),
|
|
password=os.getenv("MARIA_PASS"),
|
|
host="localhost",
|
|
port=3306,
|
|
database=os.getenv("MARIA_DB"),
|
|
local_infile=True,
|
|
)
|
|
db_name = "mariadb"
|
|
|
|
return (db_name, connection)
|
|
|
|
|
|
def _create_tables_force(cursor): # type: ignore
|
|
|
|
cursor.execute("DROP TABLE IF EXISTS auth")
|
|
cursor.execute("DROP TABLE IF EXISTS publ")
|
|
|
|
cursor.execute("""CREATE TABLE auth (
|
|
name VARCHAR(49),
|
|
pubid VARCHAR(129)
|
|
|
|
)""")
|
|
|
|
cursor.execute("""
|
|
CREATE TABLE publ (
|
|
pubid VARCHAR(129),
|
|
type VARCHAR(13),
|
|
title VARCHAR(700),
|
|
booktitle VARCHAR(132),
|
|
year VARCHAR(4),
|
|
publisher VARCHAR(196)
|
|
)
|
|
""")
|
|
|
|
|
|
def setupBoth(index_config):
|
|
create_distribute_postgres(index_config)
|
|
create_distribute_maria(index_config)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument(
|
|
"index", choices=INDEX_CONFIGS.keys(), help="Index configuration to apply"
|
|
)
|
|
args = parser.parse_args()
|
|
|
|
print(f"Index: {args.index}")
|
|
setupBoth(args.index)
|