⭐Artículos de la serie de análisis de código fuente de la base de datos OpenGauss——Predicción de tiempo de consulta de IA⭐

El artículo anterior presentó el contenido relevante de " 8.5 Recopilación de índices, predicción y detección de anomalías ". En este artículo, presentamos el contenido relevante y emocionante de "8.6 Predicción de tiempo de consulta de IA".

8.6 Predicción de tiempo de consulta de IA

La función "Slow SQL Discovery" se introdujo anteriormente. El escenario típico de esta función es la inspección antes del lanzamiento de nuevos servicios, y la fuente de entrada son los datos de canalización de SQL recopilados por adelantado. La función de descubrimiento lento de SQL se utiliza principalmente en la inspección por lotes de varias instrucciones SQL, lo que requiere que las instrucciones SQL se hayan ejecutado antes, por lo que los resultados proporcionados son principalmente cualitativos y, en algunos escenarios, puede ser difícil cumplir con los requisitos del usuario para precisión de la evaluación.
Por lo tanto, para compensar las deficiencias de los escenarios anteriores, cumplir con los requisitos de predicción de tiempo SQL más precisos del usuario y allanar el camino para el optimizador de IA, se realizan las funciones descritas en este capítulo.
Debido a la naturaleza compleja de los escenarios comerciales reales, los modelos de estimación de costos estáticos existentes para las bases de datos a menudo son inexactos en los resultados estadísticos y se seleccionan algunas rutas con planes de ejecución deficientes. Por lo tanto, para los escenarios complejos anteriores, se requiere que el modelo de estimación de costos de la base de datos tenga la capacidad de autoactualización. La función principal de esta función es estimar el tiempo de consulta y la cardinalidad de la instrucción SQL ejecutada actualmente en función de los datos históricos de la instrucción de consulta.

8.6.1 Escenarios de uso

La premisa del análisis de consultas de IA es obtener el plan de ejecución. En primer lugar, es necesario recopilar el plan de consulta real de las consultas complejas (incluida la estructura del plan, el tipo de operador, las fuentes de datos relacionadas, las condiciones de filtrado, etc.), el tiempo de ejecución real de cada nodo del operador, el costo estimado por el optimizador y el número real de filas devueltas durante la ejecución de la consulta según las necesidades del usuario, el número de filas estimado por el optimizador, el número de subprocesos simultáneos de SMP y otra información. Regístrelo en la tabla de datos y realice una gestión persistente, incluida la limpieza regular de invalidación de datos.
Esta función se divide principalmente en dos aspectos, uno es la estimación del número de filas y el otro es la predicción de consultas, el primero es el requisito previo para que el segundo prediga si es bueno o malo. En la actualidad, openGauss estima el tamaño del conjunto de resultados de cada capa del plan de ejecución en función del aprendizaje en línea, que es solo para visualización y no afecta la generación del plan de ejecución. El seguimiento puede ayudar al optimizador a estimar el conjunto de resultados con mayor precisión, a fin de obtener un mejor plan de ejecución.
En la etapa actual, esta demanda proporcionará funciones del sistema para la predicción y la agregará para explicar la comparación y verificación reales.

8.6.2 Tecnologías existentes

En la actualidad, en el campo de AI4DB, hay muchos intentos de estimar el número de filas y predecir el retraso de la consulta en función del aprendizaje automático.

1. Método tradicional

Como dijo el experto en optimización de bases de datos Guy Lohman en el blog ¿La optimización de consultas es un problema "resuelto"?, el "talón de Aquiles" de la predicción tradicional del rendimiento de consultas de bases de datos es la estimación del tamaño del conjunto de resultados intermedios. Para la estimación del número de filas, el método tradicional de estimación del número de filas basado en información estadística se basa principalmente en tres tipos de supuestos.
(1) Suposición de distribución independiente de los datos.
(2) Suposición de distribución uniforme.
(3) Supuestos de clave primaria y externa.
Sin embargo, en escenarios reales, los datos a menudo tienen cierta correlación e inclinación. En este momento, las suposiciones anteriores pueden romperse, lo que resulta en errores de varios órdenes de magnitud en los optimizadores de bases de datos tradicionales al estimar el tamaño de los conjuntos de resultados intermedios para uniones de varias tablas. .
Desde el año 2000, se han propuesto métodos estadísticos representados por estimación basada en muestreo, estimación de función de densidad kernel basada en muestreo e histogramas de varias columnas para resolver los problemas de estimación causados ​​por la correlación de datos. Sin embargo, todos estos métodos tienen un problema común, es decir, el modelo no se puede mantener de forma incremental, y la recopilación de esta información estadística adicional aumentará los gastos generales de mantenimiento de la base de datos. Ha mejorado mucho la tasa de precisión, pero no ha sido ampliamente adoptado por principales fabricantes de bases de datos.
Los métodos tradicionales de predicción del rendimiento se basan principalmente en modelos de costos, que tienen desventajas obvias en los siguientes aspectos.
(1) Precisión: con la evolución continua de la arquitectura de hardware subyacente y la tecnología de optimización, la complejidad del modelo de predicción de rendimiento real está lejos de ser modelada por un modelo lineal.
(2) Escalabilidad: el costo de desarrollo del modelo de costos es relativamente alto y no puede optimizar los escenarios específicos del usuario de manera integral.
(3) Capacidad de calibración: la flexibilidad del modelo de costos está limitada a los coeficientes utilizados en la suma lineal de cada dimensión de recursos, así como algunos costos de penalización. La flexibilidad es pobre y es difícil para los usuarios calibrar en el uso real.
(4) Oportunidad: El modelo de costos se basa en la recopilación y uso de información estadística, actualmente no existe un método de mantenimiento incremental, lo que conduce a fallas a largo plazo de la información estadística en escenarios con alta movilidad de datos.

2. Métodos de aprendizaje automático

Las ventajas de los modelos de aprendizaje automático en las dimensiones de complejidad, calibrabilidad y mantenibilidad incremental del modelo pueden compensar las deficiencias de los modelos de costos de optimización tradicionales. direcciones.
Además de los métodos relacionados presentados en la sección de descubrimiento lento de SQL en la Sección 8.3 anterior, el modelo de estimador de costos aprendidos de la Universidad de Tsinghua se basa en el aprendizaje multitarea y el método de incrustación de palabras de las condiciones de los caracteres para mejorar aún más la precisión de la predicción.
Hasta ahora, aunque el método de aprendizaje automático ha logrado una alta tasa de precisión a partir de los resultados experimentales, los cambios continuos en la distribución de datos en escenarios comerciales reales presentan requisitos para la capacidad de aprendizaje en línea del modelo. openGauss adopta un modelo de aprendizaje en línea basado en datos, recopila continuamente información histórica sobre el rendimiento del trabajo a través del kernel y utiliza el modelo R-LSTM (memoria recursiva a largo plazo a corto plazo, red de memoria recursiva a largo plazo a corto plazo) en el lado del motor de IA para determinar el retraso de la consulta a nivel de operador y los tamaños de conjuntos de resultados intermedios para la predicción.

8.6.3 Principio de implementación

inserte la descripción de la imagen aquí

Figura 8-15 Diagrama esquemático de la arquitectura de predicción del rendimiento de consultas de IA

En general, la predicción del rendimiento de las consultas consta de dos partes: el lado del núcleo de la base de datos y el lado del motor de IA, como se muestra en la Figura 8-15.
(1) Además de proporcionar las funciones básicas de la base de datos, el lado del kernel de la base de datos también necesita recopilar y conservar datos históricos y enviar solicitudes HTTPS al lado del motor de IA a través de curl.
(2) AI Engine proporciona interfaces como entrenamiento de modelos, predicción de ejecución y gestión de modelos. El servidor basado en el marco Flask acepta solicitudes HTTPS. El proceso se muestra en la Figura 8-16.
inserte la descripción de la imagen aquí

Figura 8-16 Diagrama esquemático de la relación entre el kernel de la base de datos y el proceso de AI Engine

Después de habilitar los parámetros relacionados con la recopilación de datos (que pueden afectar el rendimiento en aproximadamente un 5 %, dependiendo de la carga comercial real), los datos históricos de rendimiento se recopilan de forma persistente en las tablas del sistema de la base de datos para el entrenamiento del modelo.
Antes del entrenamiento del modelo, los usuarios deben configurar los parámetros del modelo (consulte 8.6.5 Ejemplo de uso para obtener más información). Después de que se emita el comando de capacitación del usuario, el proceso del kernel enviará una solicitud de configuración al lado del motor AI para inicializar el modelo de aprendizaje automático. La Figura 8-17 muestra la secuencia del proceso de configuración.
inserte la descripción de la imagen aquí

Figura 8-17 Diagrama de secuencia del proceso de configuración

Una vez que la configuración del modelo es exitosa, el proceso del kernel envía una solicitud de entrenamiento al lado del motor AI para activar el entrenamiento, como se muestra en la Figura 8-18.
inserte la descripción de la imagen aquí

Figura 8-18 Diagrama de secuencia del proceso de tren Después de entrenar el modelo, el usuario emite una instrucción de predicción y la base de datos primero enviará una solicitud de configuración al lado de AI Engine para cargar el modelo. envíe una solicitud de predicción para obtener el resultado de la predicción, como se muestra en la Figura 8-19 Mostrar. Figura 8-19 Diagrama de secuencia del proceso completo de predicción del modelo, que se divide en dos etapas: configuración y predicción. Esta arquitectura de características admite múltiples modelos. Actualmente, se ha implementado el modelo R-LSTM. La arquitectura del modelo se muestra en la Figura 8-20. En el plan, el orden de ejecución de los operadores también afecta el desempeño de los operadores. Con base en esta función, usamos el modelo de red neuronal LSTM para conocer las dependencias significativas entre los operadores en el plan y apuntar a la estructura del modelo, la función de pérdida, el algoritmo de optimización, etc. de acuerdo con el escenario de predicción de tiempo/número de fila Optimizado para mejorar el precisión del aprendizaje y la predicción en este escenario. Entrada: árbol del plan de consulta, tipo de operador en cada nodo, nombre de tabla correspondiente, nombre de columna y condiciones de filtro. Salida: número de filas, tiempo de inicio, tiempo total, memoria máxima. En la etapa de codificación, cada nodo del plan se codifica en una longitud fija y se conecta a una secuencia como el valor de característica de la red neuronal LSTM de entrada. LSTM tiene una red en cadena compuesta por múltiples módulos de red neuronal repetidos, y cada módulo tiene tres funciones para determinar qué información de la secuencia histórica pasará al módulo de red de la siguiente secuencia. El valor de salida h_t del último módulo es el resultado de predicción devuelto por el modelo.

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
Entre ellos, Хt es la entrada del módulo de temporización actual, ht-₁ es la entrada del módulo de temporización actual, que es la información de salida de la temporización anterior, use la función sigmoide (σ) para obtener la parte de Οt para ser salida en el estado de celda actual; Ct representa todo el tiempo histórico La información retenida es procesada por la función tanh y multiplicada por la información de salida del estado actual Οt para obtener la salida ht de este estado, y el resultado de predicción del vector unidimensional [ tiempo de inicio, tiempo total, cardinalidad] con tres elementos se compara con los datos reales, utilizando la relación de error para calcular la función de pérdida del modelo.
inserte la descripción de la imagen aquí

Figura 8-20 Diagrama de arquitectura del modelo

8.6.4 Análisis de código fuente clave

1. Estructura del proyecto

La ruta del archivo principal involucrada en el lado de AI Engine es openGauss-server/src/gausskernel/dbmind/tools/predictor, y su estructura de archivos se muestra en la Tabla 8-13.

Tabla 8-13 Estructura de archivos de AI Engine

estructura de archivos

ilustrar

instalar

Ruta de archivo necesaria para la implementación

instalar/ca_ext.txt

perfil de certificado

instalar/requisitos-gpu.txt

Use GPU (unidad de procesamiento de gráficos, procesador de gráficos) para entrenar la lista de bibliotecas dependientes

instalar/requisitos.txt

Lista de bibliotecas dependientes utilizadas para el entrenamiento de CPU

instalar/ssl.sh

Script de generación de certificados

pitón

ruta del código del proyecto

python/certificados.py

comunicación encriptada

pitón/e_log

ruta de registro del sistema

pitón/registro

Ruta del registro de entrenamiento del modelo

python/log.conf

archivo de configuración

python/modelo.py

modelo de aprendizaje automático

python/ejecutar.py

función principal del servidor

python/modelos_guardados

Punto de control de entrenamiento modelo

python/configuraciones.py

Archivo de configuración del proyecto

python/cargas

Ruta de almacenamiento del archivo de transferencia Curl

La ruta del archivo involucrada principalmente en el lado del kernel es openGauss-server/src/gausskernel/optimizer/util/learn, y su estructura de archivos se muestra en la Tabla 8-14.

Tabla 8-14 Estructura de archivos principal del lado del kernel

estructura de archivos

ilustrar

com.cpp

Implementación de código de capa de comunicación

codificación.cpp

codificación de datos

ml_modelo.cpp

Interfaz de llamada de modelo genérico

plan_tree_model.cpp

Interfaz de llamada del modelo de árbol

2. Proceso de formación

La interfaz de entrenamiento del modelo en el lado del kernel se implementa a través de la función ModelTrainInternal.Las partes clave de esta función son las siguientes:

static void ModelTrainInternal(const char* templateName, const char* modelName, ModelAccuracy** mAcc)
{
  …
    /* 对于树形模型调用对应的训练接口 */
    char* trainResultJson = TreeModelTrain(modelinfo, labels);
    /* 解析返回结果 */
    …
    ModelTrainInfo* info = GetModelTrainInfo(jsonObj);
    cJSON_Delete(jsonObj);
    /* 更新模型信息 */
    Relation modelRel = heap_open(OptModelRelationId, RowExclusiveLock);
   …
    UpdateTrainRes(values, datumsMax, datumsAcc, nLabel, mAcc, info, labels);

    HeapTuple modelTuple = SearchSysCache1(OPTMODEL, CStringGetDatum(modelName));
   …
    HeapTuple newTuple = heap_modify_tuple(modelTuple, RelationGetDescr(modelRel), values, nulls, replaces);
    simple_heap_update(modelRel, &newTuple->t_self, newTuple);
CatalogUpdateIndexes(modelRel, newTuple);
…
}

La interfaz de entrenamiento del modelo de árbol en el lado del kernel se implementa a través de la función TreeModelTrain, y el código central es el siguiente:

char* TreeModelTrain(Form_gs_opt_model modelinfo, char* labels)
{
    char* filename = (char*)palloc0(sizeof(char) * MAX_LEN_TEXT);
    char* buf = NULL;
    /* configure阶段 */
    ConfigureModel(modelinfo, labels, &filename);

    /* 将编码好的数据写入临时文件 */
    SaveDataToFile(filename);

    /* Train阶段 */
    buf = TrainModel(modelinfo, filename);
    return buf;
}

El URI del servicio web configurado en el lado de AI Engine es /configure, y el URI de la fase de entrenamiento es /train. El siguiente fragmento de código muestra el proceso de entrenamiento.

  def fit(self, filename):
        keras.backend.clear_session()
        set_session(self.session)
        with self.graph.as_default():
            # 根据模型入参和出参维度变化情况,判断是否需要初始化模型
            feature, label, need_init = self.parse(filename) 
            os.environ['CUDA_VISIBLE_DEVICES'] = '0'
            epsilon = self.model_info.make_epsilon()
            if need_init: # 冷启动训练
                epoch_start = 0
                self.model = self._build_model(epsilon)
            else: # 增量训练
                epoch_start = int(self.model_info.last_epoch)
                ratio_error = ratio_error_loss_wrapper(epsilon)
                ratio_acc_2 = ratio_error_acc_wrapper(epsilon, 2)
                self.model = load_model(self.model_info.model_path,
                                        custom_objects={'ratio_error': ratio_error, 'ratio_acc': ratio_acc_2})
            self.model_info.last_epoch = int(self.model_info.max_epoch) + epoch_start
            self.model_info.dump_dict()
            log_path = os.path.join(settings.PATH_LOG, self.model_info.model_name + '_log.json')
            if not os.path.exists(log_path):
                os.mknod(log_path, mode=0o600)
            # 训练日志记录回调函数
            json_logging_callback = LossHistory(log_path, self.model_info.model_name, self.model_info.last_epoch)
            # 数据分割
            X_train, X_val, y_train, y_val = \
                train_test_split(feature, label, test_size=0.1)
            # 模型训练
            self.model.fit(X_train, y_train, epochs=self.model_info.last_epoch,
                           batch_size=int(self.model_info.batch_size), validation_data=(X_val, y_val),
                           verbose=0, initial_epoch=epoch_start, callbacks=[json_logging_callback])
            # 记录模型checkpoint
            self.model.save(self.model_info.model_path)
            val_pred = self.model.predict(X_val)
            val_re = get_ratio_errors_general(val_pred, y_val, epsilon)
            self.model_logger.debug(val_re)
            del self.model
            return val_re

3. Proceso de previsión

El proceso de predicción del modelo en el lado del kernel se implementa principalmente a través de la función ModelPredictInternal. El proceso de predicción del modelo de árbol se implementa a través de la función TreeModelPredict. El proceso de predicción del modelo de árbol en el lado del kernel tomará algunas señales para comunicarse con AI Engine. El proceso de comunicación es el siguiente:

char* TreeModelPredict(const char* modelName, char* filepath, const char* ip, int port)
{
    …
    if (!TryConnectRemoteServer(conninfo, &buf)) {
        DestroyConnInfo(conninfo);
        ParseResBuf(buf, filepath, "AI engine connection failed.");
        return buf;
    }

    switch (buf[0]) {
        case '0': {
            ereport(NOTICE, (errmodule(MOD_OPT_AI), errmsg("Model setup successfully.")));
            break;
        }
        case 'M': {
            ParseResBuf(buf, filepath, "Internal error: missing compulsory key.");
            break;
        }
…
    }
    /* Predict阶段 */
    …
    if (!TryConnectRemoteServer(conninfo, &buf)) {
        ParseResBuf(buf, filepath, "AI engine connection failed.");
        return buf;
    }
    switch (buf[0]) {
        case 'M': {
            ParseResBuf(buf, filepath, "Internal error: fail to load the file to predict.");
            break;
        }
        case 'S': {
            ParseResBuf(buf, filepath, "Internal error: session is not loaded, model setup required.");
            break;
        }
        default: {
            break;
        }
    }
    return buf;
}

La interfaz web del proceso de configuración en el lado de AI Engine es /model_setup, y la interfaz web de la fase de predicción es /predict, y sus protocolos son ambos Post.

4. Codificación de datos

La codificación de datos se divide en las siguientes dos dimensiones.
(1) Dimensión del operador: incluye los atributos de cada operador del plan de ejecución, como se muestra en la Tabla 8-15.

Tabla 8-15 Dimensiones del operador

Nombre del Atributo

significado

estrategia de codificación

nombreopción

tipo de operador

uno-caliente

Orientación

formato de almacenamiento de tupla de retorno

uno-caliente

Estrategia

atributo lógico

uno-caliente

Opciones

propiedades físicas

uno-caliente

Cuales

predicado

picadillo

Proyección

columna proyectada de retorno

picadillo

(2) Dimensión de planificación.
Para cada operador, además de sus atributos inherentes, openGauss también registra la identificación de la consulta, la identificación del nodo del plan y la identificación del nodo principal. En la fase de entrenamiento/predicción, use esta información para reconstruir la información del operador en una estructura de plan de árbol, y la El árbol del plan secundario se puede construir de forma recursiva para mejorar los datos, mejorando así la capacidad de generalización del modelo. La estructura de datos de árbol se muestra en la Figura 8-21.
inserte la descripción de la imagen aquí

Figura 8-21 Diagrama esquemático de la estructura de datos de árbol La codificación de datos de árbol en el lado del kernel se realiza a través de la función GetOPTEncoding.

5. Estructura del modelo

Para el análisis, entrenamiento y predicción del modelo de AI Engine, consulte el capítulo 8.6.4 El siguiente código muestra la estructura del modelo.

class RnnModel():
    def _build_model(self, epsilon):
        model = Sequential()
        model.add(LSTM(units=int(self.model_info.hidden_units), return_sequences=True, input_shape=(None, int(self.model_info.feature_length))))
        model.add(LSTM(units=int(self.model_info.hidden_units), return_sequences=False))
        model.add(Dense(units=int(self.model_info.hidden_units), activation='relu'))
        model.add(Dense(units=int(self.model_info.hidden_units), activation='relu'))
        model.add(Dense(units=int(self.model_info.label_length), activation='sigmoid'))
        optimizer = keras.optimizers.Adadelta(lr=float(self.model_info.learning_rate), rho=0.95)
        ratio_error = ratio_error_loss_wrapper(epsilon)
        ratio_acc_2 = ratio_error_acc_wrapper(epsilon, 2)
        model.compile(loss=ratio_error, metrics=[ratio_acc_2], optimizer=optimizer)
        return model

La función de pérdida de AI Engine usa un error de proporción (qerror se usa en algunas publicaciones). En comparación con MRE y MSE, la ventaja de esta función de pérdida es que puede castigar por igual la sobreestimación y la subestimación. La fórmula es: ε se declara como rendimiento
inserte la descripción de la imagen aquí
. valor infinitesimal del valor predicho para evitar que el denominador sea 0.

8.6.5 Ejemplo de uso

Un ejemplo del uso de la función de predicción de tiempo de consulta de IA es el siguiente.
① Defina el modelo de predicción de rendimiento, el código es el siguiente:

INSERT INTO gs_opt_model VALUES(‘rlstm’, ‘model_name’, ‘host_ip’, ‘port’);

② Inicie la recopilación de datos a través de los parámetros GUC, configure la lista de parámetros, el código es el siguiente:

enable_resource_track = on;
enable_resource_record = on;

③ Codifique los datos de entrenamiento, el código es el siguiente:

SELECT gather_encoding_info('db_name');

④ Modelo de calibración, el código es el siguiente:

SELECT model_train_opt('template_name', 'model_name');

⑤ Supervise el estado de entrenamiento, el código es el siguiente:

SELECT track_train_process('host_ip', 'port');

⑥ Prediga el rendimiento de la consulta SQL a través de la instrucción SQL explicativa, el código es el siguiente:

EXPLAIN (..., predictor 'model_name') SELECT ...

Obtenga los resultados, donde la columna "p-time" es la predicción de la etiqueta.

Row Adapter  (cost=110481.35..110481.35 rows=100 p-time=99..182 width=100) (actual time=375.158..375.160 rows=2 loops=1)

8.6.6 Ruta de Evolución

La capacidad de generalización del modelo actual es insuficiente, ya que se basa en componentes externos de AI Engine, y la red de aprendizaje profundo es relativamente pesada, lo que dificultará la implementación; el modelo necesita datos para el entrenamiento y la conexión en la etapa de arranque en frío no es lo suficientemente suave El seguimiento de los siguientes aspectos evoluciona.
(1) Agregue modelos de diferente complejidad y admita el análisis de fusión de múltiples modelos para proporcionar resultados de predicción de modelos más sólidos y confianza.
(2) AI Engine está considerando unirse a la cola de tareas. Actualmente, solo admite predicción/entrenamiento simultáneo único, y se pueden considerar varios servidores para negocios simultáneos.
(3) Con base en la mejora del aprendizaje en línea/aprendizaje de transferencia, considere agregar un costo de penalización de anclaje a la función de pérdida para evitar el problema del olvido del desastre. Al mismo tiempo, optimice el modo de administración de datos, considere el mecanismo de puntuación de datos y asignar pesos de acuerdo con la oportunidad de los datos.
(4) Integre esta función con el optimizador para explorar métodos de selección de rutas basados ​​en IA.

Gracias por conocer el maravilloso contenido de "8.6 Predicción de tiempo de consulta de IA" en el Capítulo 8 Tecnología de IA. En el próximo artículo, presentaremos el contenido relevante de "8.7 DeepSQL".
Manténganse al tanto.

Supongo que te gusta

Origin blog.csdn.net/GaussDB/article/details/120409020
Recomendado
Clasificación