Changes between Initial Version and Version 1 of OtherDevelopments


Ignore:
Timestamp:
05/28/26 09:29:22 (2 weeks ago)
Author:
221296
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • OtherDevelopments

    v1 v1  
     1== SQL Performance and Index Optimization ==
     2
     3The goal of this phase is to analyze and improve the performance of the most important database operations in the Online Learning Platform Management System.
     4
     5The application contains several frequent operations:
     6
     7browsing and filtering courses
     8checking existing enrollments
     9validating active user subscriptions
     10loading course modules and lessons
     11managing support tickets
     12generating reports for enrollments, certificates and quiz attempts
     13
     14The following indexes are not automatically created by primary key constraints, but they can improve the performance of WHERE filters, JOIN operations and report queries.
     15
     16== Testing Methodology ==
     17
     18The performance analysis is done using PostgreSQL EXPLAIN ANALYZE.
     19
     20The testing process is:
     21
     22first, the query is executed without additional indexes
     23then, the required index is created
     24the same query is executed again
     25the execution plan and execution time are compared
     26
     27This allows us to check whether PostgreSQL uses Seq Scan, Index Scan or another optimized query plan.
     28
     29== Scenario 1: Course Browsing and Filtering ==
     30
     31Users frequently browse available courses and filter them by course status, name or price.
     32
     33SQL query:
     34
     35{{{
     36EXPLAIN ANALYZE
     37SELECT c.course_id, c.name, c.price, c.status
     38FROM course c
     39WHERE c.status = 'ACTIVE'
     40ORDER BY c.price;
     41}}}
     42
     43Indexes:
     44
     45{{{
     46CREATE INDEX IF NOT EXISTS idx_course_status_price
     47ON course(status, price);
     48
     49CREATE INDEX IF NOT EXISTS idx_course_name
     50ON course(name);
     51}}}
     52
     53Explanation:
     54
     55The composite index on (status, price) is useful because the query filters by status and sorts by price.
     56
     57The index on name improves course searching by course name.
     58
     59== Scenario 2: Enrollment Checking ==
     60
     61Before a user enrolls in a course, the system checks whether the user is already enrolled in that course.
     62
     63SQL query:
     64
     65{{{
     66EXPLAIN ANALYZE
     67SELECT e.enrollment_id, e.user_id, e.course_id, e.completion_status
     68FROM enrollment e
     69WHERE e.user_id = 1
     70AND e.course_id = 3;
     71}}}
     72
     73Index:
     74
     75{{{
     76CREATE INDEX IF NOT EXISTS idx_enrollment_user_course
     77ON enrollment(user_id, course_id);
     78}}}
     79
     80Explanation:
     81
     82This index is useful because the application frequently searches enrollments by both user_id and course_id.
     83
     84Without this index, PostgreSQL may scan the whole enrollment table. With the index, the lookup is faster and more direct.
     85
     86== Scenario 3: Active Subscription Validation ==
     87
     88When a user wants to access course content, the system checks whether the user has an active subscription.
     89
     90SQL query:
     91
     92{{{
     93EXPLAIN ANALYZE
     94SELECT us.subscription_id, us.user_id, us.plan_id, us.status, us.end_date
     95FROM user_subscription us
     96WHERE us.user_id = 1
     97AND us.status = 'ACTIVE'
     98AND us.end_date >= CURRENT_DATE;
     99}}}
     100
     101Index:
     102
     103{{{
     104CREATE INDEX IF NOT EXISTS idx_user_subscription_active
     105ON user_subscription(user_id, status, end_date);
     106}}}
     107
     108Explanation:
     109
     110The index improves subscription validation because the query filters by user_id, status and end_date.
     111
     112This is important because subscription validation is performed before allowing access to paid course content.
     113
     114== Scenario 4: Instructor Course Management ==
     115
     116Instructors frequently manage their own courses. The system displays all courses created by a selected instructor.
     117
     118SQL query:
     119
     120{{{
     121EXPLAIN ANALYZE
     122SELECT c.course_id, c.name, c.price, c.status
     123FROM course c
     124WHERE c.instructor_id = 5;
     125}}}
     126
     127Index:
     128
     129{{{
     130CREATE INDEX IF NOT EXISTS idx_course_instructor_id
     131ON course(instructor_id);
     132}}}
     133
     134Explanation:
     135
     136The instructor_id column is used for filtering courses by instructor. This index improves the performance of the instructor dashboard.
     137
     138== Scenario 5: Course Content Loading ==
     139
     140When a user opens a course, the application loads all modules and lessons for that course.
     141
     142SQL query:
     143
     144{{{
     145EXPLAIN ANALYZE
     146SELECT
     147m.module_id,
     148m.title AS module_title,
     149l.lesson_id,
     150l.title AS lesson_title
     151FROM module m
     152JOIN lesson l ON l.module_id = m.module_id
     153WHERE m.course_id = 3
     154ORDER BY m.module_id, l.lesson_id;
     155}}}
     156
     157Indexes:
     158
     159{{{
     160CREATE INDEX IF NOT EXISTS idx_module_course_id
     161ON module(course_id);
     162
     163CREATE INDEX IF NOT EXISTS idx_lesson_module_id
     164ON lesson(module_id);
     165}}}
     166
     167Explanation:
     168
     169The index on module(course_id) improves loading modules for a selected course.
     170
     171The index on lesson(module_id) improves loading lessons for each module.
     172
     173== Scenario 6: Admin Support Ticket Filtering ==
     174
     175Administrators frequently filter support tickets by status and check the newest tickets first.
     176
     177SQL query:
     178
     179{{{
     180EXPLAIN ANALYZE
     181SELECT st.ticket_id, st.subject, st.status, st.created_at
     182FROM support_ticket st
     183WHERE st.status = 'OPEN'
     184ORDER BY st.created_at DESC;
     185}}}
     186
     187Index:
     188
     189{{{
     190CREATE INDEX IF NOT EXISTS idx_support_ticket_status_created
     191ON support_ticket(status, created_at DESC);
     192}}}
     193
     194Explanation:
     195
     196This index is useful because the admin panel filters tickets by status and sorts them by created_at.
     197
     198== Scenario 7: Annual Enrollment and Certificate Report ==
     199
     200This report analyzes enrollments, completed courses and issued certificates per year.
     201
     202SQL query:
     203
     204{{{
     205EXPLAIN ANALYZE
     206SELECT
     207EXTRACT(YEAR FROM e.enroll_date) AS year,
     208COUNT(DISTINCT e.enrollment_id) AS total_enrollments,
     209COUNT(DISTINCT CASE
     210WHEN e.completion_status = 'COMPLETED' THEN e.enrollment_id
     211END) AS completed_enrollments,
     212COUNT(DISTINCT c.certificate_id) AS issued_certificates,
     213AVG(e.progress_percentage) AS average_progress
     214FROM enrollment e
     215LEFT JOIN certificate c ON c.enrollment_id = e.enrollment_id
     216GROUP BY EXTRACT(YEAR FROM e.enroll_date)
     217ORDER BY year;
     218}}}
     219
     220Indexes:
     221
     222{{{
     223CREATE INDEX IF NOT EXISTS idx_enrollment_enroll_date
     224ON enrollment(enroll_date);
     225
     226CREATE INDEX IF NOT EXISTS idx_enrollment_completion_status
     227ON enrollment(completion_status);
     228
     229CREATE INDEX IF NOT EXISTS idx_certificate_enrollment_id
     230ON certificate(enrollment_id);
     231}}}
     232
     233Explanation:
     234
     235The index on enroll_date improves time-based reports.
     236
     237The index on completion_status helps when filtering completed enrollments.
     238
     239The index on certificate(enrollment_id) improves the join between certificate and enrollment.
     240
     241== Scenario 8: Quiz Attempts Report ==
     242
     243The system can analyze quiz attempts by user, quiz and attempt date.
     244
     245SQL query:
     246
     247{{{
     248EXPLAIN ANALYZE
     249SELECT
     250qa.user_id,
     251qa.quiz_id,
     252COUNT(*) AS total_attempts,
     253AVG(qa.score) AS average_score
     254FROM quiz_attempt qa
     255GROUP BY qa.user_id, qa.quiz_id
     256ORDER BY qa.user_id;
     257}}}
     258
     259Indexes:
     260
     261{{{
     262CREATE INDEX IF NOT EXISTS idx_quiz_attempt_user_id
     263ON quiz_attempt(user_id);
     264
     265CREATE INDEX IF NOT EXISTS idx_quiz_attempt_quiz_id
     266ON quiz_attempt(quiz_id);
     267
     268CREATE INDEX IF NOT EXISTS idx_quiz_attempt_date
     269ON quiz_attempt(attempt_date);
     270}}}
     271
     272Explanation:
     273
     274These indexes improve reports that analyze quiz attempts by user, quiz or date.