Повышение производительности при извлечении данных из базы данных oracle - PullRequest
0 голосов
/ 23 января 2020

диаграмма отношений сущностей

Структура моей таблицы базы данных выглядит следующим образом:

Таблица курса: (id (первичный ключ), name, descr и другие поля)

Таблица взаимосвязей активности курса: (идентификатор курса, идентификатор активности) (составной ключ - оба столбца)

Таблица взаимосвязи формата курса: (идентификатор курса, идентификатор формата) ( составной ключ - оба столбца)

таблица соотношения экзамена курса: (идентификатор курса, идентификатор экзамена) (составной ключ - оба столбца)

В настоящее время я извлекаю его из базы данных следующее:

Получить курс из запроса db: SELECT по курсу на основе условия.

В java коде: сохраните эти данные в Map, ключ: courseId и значение: course dto

final Map<String, CourseInfo> data = new LinkedHashMap<>();

Теперь все идентификаторы курсов сохраняются в ключе карты, используя это Я получу все FormatIds , ActivityIds и ExamIds

Это будет три отдельных запроса к соответствующим таблицам, и каждый результат будет сохранен в CourseInfo.List formatIds, CourseInfo.List ActivityIds, CourseInfo.List examIds, CourseInfos находятся в карте.

public static void loadCourseRelatedData(final Connection connection, 
            final Map<String, CourseInfo> data)
            throws SQLException {
        if (!data.isEmpty()) {


            // Load the related data for : ActivityIds
            loadFormatOfferingRelatedDataByTable(connection,  COURSE_ACTIVITY_REL_TABLE_NAME ,
                    COURSE_ACTIVITY_REL_FIELDS.ACTIVITY_ID.name(),
                    COURSE_ACTIVITY_REL_FIELDS.COURSE_ID.name(), data);

        // Load the related data for : formatIds
            loadFormatOfferingRelatedDataByTable(connection,  COURSE_FORMAT_REL_TABLE_NAME ,
                    COURSE_FORMAT_REL_FIELDS.FORMAT_ID.name(),
                    COURSE_FORMAT_REL_FIELDS.COURSE_ID.name(), data);

            // Load the related data for : ExamIds
            loadFormatOfferingRelatedDataByTable(connection,  COURSE_EXAM_REL_TABLE_NAME ,
                    COURSE_EXAM_REL_FIELDS.EXAM_ID.name(),
                    COURSE_EXAM_REL_FIELDS.COURSE_ID.name(), data);

        }
    }

Код loadCourseRelatedData выглядит следующим образом

private static void loadCourseRelatedDataByTable(
            final Connection connection, 
            final String tableName,
            final String listFieldName,
            final String parentField,
            final Map<String, CourseInfo> data)
            throws SQLException {

        StringBuilder sql = new StringBuilder();
        try {
            sql.append(SELECT).append(NEW_LINE);
            sql.append(listFieldName).append(" , ").append(parentField).append(NEW_LINE);
            sql.append(FROM).append(NEW_LINE);
            sql.append(tableName).append(NEW_LINE);
        sql.append(WHERE).append(NEW_LINE);
            sql.append(parentField).append(" in ( ").append(NEW_LINE);
            sql.append(getCommaSeperatedString(data.size(), "?")).append(NEW_LINE);
            sql.append(")");


            try (PreparedStatement statement = connection.prepareStatement(sql.toString())) { 

                    // set the perameter
                    int counter = 1;
                    for (String parentId : data.keySet()) {
                        statement.setString(counter++, parentId);
                    }


                try (ResultSet resultSet = statement.executeQuery()) {
                    while (resultSet.next()) {
                        String parentId = resultSet.getString(parentField);
                        String relatedId = resultSet.getString(listFieldName);
                        CourseInfo info = data.get(parentId);


                            switch (tableName) {

                                case COURSE_ACTIVITY_REL_TABLE_NAME:
                                    info.getActivityIds().add(relatedId);
                                    break;

                                case COURSE_FORMAT_REL_TABLE_NAME:
                                    info.getFormatIds().add(relatedId);
                                    break;

                                case COURSE_EXAM_REL_TABLE_NAME:
                                    info.getExamIds().add(relatedId);
                                    break;

                                default:
                                    throw new IllegalArgumentException(
                                            tableName + " : Is not valid realtive table");
                            }
                    }
                }
            }
        } catch (SQLException ex) {
            StringBuilder message = new StringBuilder();
            message.append("\t Related Sql--> ").append(sql).append(NEW_LINE);
            // add the cause Message
            message.append(ex.getMessage());
            throw new SQLException(message.toString(), ex);
        }
    }

Теперь вопрос заключается в том, как повысить производительность, избегая этих трех дополнительных вызовов БД для связанных идентификаторов?

Подход 1:

Один из подходов, который я выбрал, - это добавить поле для каждого списка, то есть formatIds, ActivityIds и examIds в Course Table, в котором будут храниться все идентификаторы с разделенными запятыми значениями при вставке.

Так что теперь у меня будут данные через запятую, разделенные в CourseTable, а также связанные таблицы.

Данные таблицы курса будут выглядеть следующим образом:

  ID   |   Name   |   FomatIds      |      ActivityIds    |       ExamIds
---------------------------------------------------------------------------------
  001  | couse.01 | for.1,for.2     |act.1, act.2, act.3  | exm.1, exm.2, exm3 
  002  | couse.02 | for.3,for.4     |act.1, act.3, act.5  | exm.1, exm.2, exm3 
.....
.....

Для всех запросов на присоединение также будут доступны связанные таблицы:

COURSE_ACTIVITY_REL_TABLE_NAME

  COURSEID |   ACTIVITY ID   
---------------------------------------------------------------------------------
  couse.01 | act.1 
  couse.01 | act.2
  couse.01 | act.3 
  couse.02 | act.1
  couse.02 | act.3
  couse.02 | act.5
.....
.....

Недостатками этого подхода являются

  • вставка и обновление курса будет немного дороже
  • главный недостаток в том, что я могу хранить значения, разделенные запятыми, до 32000 символов как VARCHAR2 (32000). Это единственный пример сущности курса, у меня в приложении много сущностей, поэтому не рекомендуется использовать CLOB вместо VARCHAR2 (32000)

Можете ли вы предложить любой другой подход, который я могу использовать улучшить производительность при получении данных значительно?

...