source: sql/perf/perf_data.sql

Last change on this file was 2853f2e, checked in by Stefan-Saveski <stefansaveski19@…>, 6 hours ago

Add performance analysis scripts and schema for educational database

  • Created performance analysis scripts for student dossier, subject pass rate, and top students per major.
  • Added indexes to improve query performance on key tables.
  • Generated bulk test data for performance analysis in the 'perf' schema.
  • Established the 'perf' schema with necessary tables and types for educational data management.
  • Property mode set to 100644
File size: 5.0 KB
Line 
1-- Bulk test data for the Phase 9 performance analysis.
2-- Generated in the `perf` schema so the official `project` data is untouched.
3SET search_path TO perf;
4
5-- ---------- faculties of scale ----------
6INSERT INTO major (id, name)
7SELECT g, 'Major ' || g FROM generate_series(1, 6) g;
8
9INSERT INTO active_semesters (id, year, type)
10SELECT row_number() OVER (), y, t
11FROM generate_series(2016, 2025) y
12CROSS JOIN (VALUES ('winter'::semester_type), ('summer'::semester_type)) AS s(t);
13
14-- 300 subjects
15INSERT INTO subjects (id, name, code, awarded_credits, dependency_credit)
16SELECT g,
17 'Subject ' || g,
18 'S' || lpad(g::TEXT, 5, '0'),
19 6,
20 CASE WHEN g % 3 = 0 THEN 6 ELSE 0 END
21FROM generate_series(1, 300) g;
22
23-- every subject offered by two programmes
24INSERT INTO major_subjects (major_id, subject_id, mandatory_semester)
25SELECT 1 + (g % 6), g, 1 + (g % 8) FROM generate_series(1, 300) g
26UNION
27SELECT 1 + ((g + 1) % 6), g, 1 + (g % 8) FROM generate_series(1, 300) g;
28
29-- ---------- people ----------
30-- 120 professors
31INSERT INTO users (id, name, embg, surname, "index", bday, email, password, role, quota, enrollment_year)
32SELECT g,
33 'Prof' || g, lpad(g::TEXT, 13, '0'), 'Surname' || g, NULL,
34 '1975-01-01'::TIMESTAMP,
35 'prof' || g || '@finki.ukim.mk', 'hash', 'prof', NULL, NULL
36FROM generate_series(1, 120) g;
37
38-- 4000 students
39INSERT INTO users (id, name, embg, surname, "index", bday, email, password, role, quota, enrollment_year)
40SELECT 1000 + g,
41 'Student' || g, lpad((1000 + g)::TEXT, 13, '0'), 'Student' || g,
42 lpad((200000 + g)::TEXT, 6, '0'),
43 '2003-01-01'::TIMESTAMP,
44 'student' || g || '@students.finki.ukim.mk', 'hash', 'student',
45 CASE WHEN g % 2 = 0 THEN 'drzavna'::quota_type ELSE 'privatna'::quota_type END,
46 2018 + (g % 7)
47FROM generate_series(1, 4000) g;
48
49INSERT INTO contact (user_id, city, municipality, address, number)
50SELECT 1000 + g, 'Skopje', 'Centar', 'Street ' || g, '070' || lpad(g::TEXT, 6, '0')
51FROM generate_series(1, 4000) g;
52
53INSERT INTO high_school (user_id, gpa, type)
54SELECT 1000 + g, 3.0 + (g % 20) / 10.0,
55 CASE WHEN g % 2 = 0 THEN 'gimnazija'::hs_type ELSE 'strucen'::hs_type END
56FROM generate_series(1, 4000) g;
57
58-- ---------- teaching schedule ----------
59-- every (semester, subject) pair taught by one professor
60INSERT INTO professour_subjects (prof_id, active_semester_id, subject_id)
61SELECT 1 + ((s.id * 7 + sub.id) % 120), s.id, sub.id
62FROM active_semesters s CROSS JOIN subjects sub;
63
64-- ---------- enrolments ----------
65-- each student enrols in 4 consecutive semesters
66INSERT INTO enrolled_semesters (user_id, quota, major_id, semester_id, created_at, last_change, completed)
67SELECT 1000 + g,
68 CASE WHEN g % 2 = 0 THEN 'drzavna'::quota_type ELSE 'privatna'::quota_type END,
69 1 + (g % 6),
70 sem,
71 now() - (interval '1 day' * (g % 900)),
72 now() - (interval '1 day' * (g % 400)),
73 CASE WHEN sem % 3 = 0 THEN now() - interval '30 days' ELSE NULL END
74FROM generate_series(1, 4000) g
75CROSS JOIN LATERAL (
76 SELECT 1 + ((g + k) % 20) AS sem FROM generate_series(0, 3) k
77) s
78ON CONFLICT (user_id, semester_id) DO NOTHING;
79
80-- five subjects per enrolment
81INSERT INTO semesters_subjects (enrolled_semesters_id, subjects_id, professor_id, signature)
82SELECT es.id,
83 ps.subject_id,
84 ps.prof_id,
85 (es.id + ps.subject_id) % 4 <> 0
86FROM enrolled_semesters es
87CROSS JOIN LATERAL (
88 SELECT p.subject_id, p.prof_id
89 FROM professour_subjects p
90 WHERE p.active_semester_id = es.semester_id
91 AND p.subject_id IN (
92 SELECT ms.subject_id FROM major_subjects ms WHERE ms.major_id = es.major_id
93 )
94 ORDER BY (p.subject_id * 13 + es.id) % 997
95 LIMIT 5
96) ps
97ON CONFLICT (enrolled_semesters_id, subjects_id) DO NOTHING;
98
99-- roughly 70% of enrolled subjects are passed
100INSERT INTO passed_subjects (enrolled_id, grade, date_passed)
101SELECT ss.id,
102 (ARRAY['6','7','8','9','10']::grade_type[])[1 + (ss.id % 5)],
103 now() - (interval '1 day' * (ss.id % 800))
104FROM semesters_subjects ss
105WHERE ss.id % 10 < 7
106ON CONFLICT (enrolled_id) DO NOTHING;
107
108-- ---------- payments and documents ----------
109INSERT INTO payment (enrollment_id, amount)
110SELECT es.id, 200 + (es.id % 5) * 100
111FROM enrolled_semesters es;
112
113INSERT INTO documents (id, type, body, cost)
114SELECT g, 'Document type ' || g, 'Body of document ' || g, 50 * g
115FROM generate_series(1, 8) g;
116
117INSERT INTO user_documents (user_id, document_id)
118SELECT 1000 + g, 1 + (g % 8) FROM generate_series(1, 4000) g
119ON CONFLICT DO NOTHING;
120
121-- sequences must catch up with the explicit ids
122SELECT setval(pg_get_serial_sequence('perf.users', 'id'), (SELECT max(id) FROM users));
123SELECT setval(pg_get_serial_sequence('perf.major', 'id'), (SELECT max(id) FROM major));
124SELECT setval(pg_get_serial_sequence('perf.active_semesters', 'id'), (SELECT max(id) FROM active_semesters));
125SELECT setval(pg_get_serial_sequence('perf.subjects', 'id'), (SELECT max(id) FROM subjects));
126SELECT setval(pg_get_serial_sequence('perf.documents', 'id'), (SELECT max(id) FROM documents));
127
128ANALYZE;
Note: See TracBrowser for help on using the repository browser.