Recursos
- Recursos de tiempo compartido (CPU, E/S, slots de consulta): gestionan las solicitudes de recursos que se encolan en los nodos hoja de la jerarquía de planificación. Las solicitudes se planifican de acuerdo con las políticas y restricciones definidas por la jerarquía. Las solicitudes de recursos se crean cuando una consulta accede al recurso correspondiente. Por ejemplo, cuando una consulta lee datos del disco o usa la CPU para el procesamiento, se crean solicitudes de recursos por cada cuanto de trabajo realizado o por la cantidad de bytes enviados o recibidos a través de un socket.
- Recursos de espacio compartido (Memoria): gestionan las asignaciones de recursos en los nodos hoja de la jerarquía de planificación. Las asignaciones pueden estar en ejecución o pendientes. Las asignaciones pendientes se bloquean hasta que se libere suficiente espacio o se desaloje (se termine) otra asignación. Las decisiones se basan en los límites y políticas definidos por la jerarquía. Existe una correspondencia uno a uno entre las asignaciones y las consultas (o actividades en segundo plano). Se crea una asignación cuando una consulta empieza a ejecutarse y se libera cuando finaliza. Las asignaciones en ejecución pueden aumentar o reducir su tamaño de forma dinámica.
Jerarquía de cargas de trabajo
max_* son por host. La carga de trabajo “user” subdivide sus recursos entre las cargas de trabajo “development” y “production”, donde “production” tiene 3 veces más recursos que “development”:
SETTINGS workload = 'name'. Consulta Workload markup para obtener más detalles.
Para personalizar la carga de trabajo, se pueden usar las siguientes opciones de configuración:
priority- (solo de tiempo compartido) las cargas de trabajo hermanas se atienden según valores de prioridad estáticos (un valor menor significa una prioridad más alta). Determina la apropiación.precedence- (solo de espacio compartido) las cargas de trabajo hermanas se admiten según valores estáticos de precedencia (un valor menor significa una precedencia más alta). Determina la expulsión y la admisión.weight- las cargas de trabajo hermanas con la misma prioridad o precedencia estática comparten los recursos según sus pesos de manera justa. Afecta a la apropiación, la expulsión y la admisión.max_io_requests- el límite del número de solicitudes de E/S concurrentes en esta carga de trabajo.max_bytes_inflight- el límite del total de bytes en curso para las solicitudes concurrentes en esta carga de trabajo.max_bytes_per_second- el límite de la tasa de lectura o escritura de bytes de esta carga de trabajo.max_burst_bytes- el número máximo de bytes que la carga de trabajo puede procesar sin que se limite su tasa (para cada recurso de forma independiente).max_concurrent_threads- el límite del número de hilos para las consultas de esta carga de trabajo.max_concurrent_threads_ratio_to_cores- lo mismo quemax_concurrent_threads, pero normalizado según el número de núcleos de CPU disponibles.max_cpus- el límite del número de núcleos de CPU para atender consultas en esta carga de trabajo.max_cpu_share- lo mismo quemax_cpus, pero normalizado según el número de núcleos de CPU disponibles.max_burst_cpu_seconds- el número máximo de segundos de CPU que la carga de trabajo puede consumir sin que se limite su tasa debido amax_cpus.max_memory- el límite de la memoria total reservada para esta carga de trabajo.
max_bytes_per_second = '10Mi' tendrá un límite de ancho de banda de 10 MB/s para cada recurso de lectura y escritura, de forma independiente. Si se requiere un límite común para lectura y escritura, considere usar el mismo recurso para el acceso READ y WRITE.
No hay forma de especificar distintas jerarquías de cargas de trabajo para diferentes recursos. Pero sí hay una manera de especificar un valor distinto de configuración de la carga de trabajo para un recurso específico:
CREATE OR REPLACE WORKLOAD.
La configuración de la carga de trabajo se convierte en un conjunto adecuado de nodos de planificación. Para obtener más detalles, consulta la descripción de los tipos y opciones de los nodos de planificación.
Marcado de carga de trabajo
workload para distinguir distintas cargas de trabajo. Si no se establece workload, se usa el valor “default”. Tenga en cuenta que también puede especificar otro valor mediante perfiles de configuración. Las restricciones de configuración pueden usarse para hacer que workload sea constante si desea que todas las consultas de un usuario se marquen con un valor fijo para la configuración workload.
workload a las actividades en segundo plano. Las fusiones y mutaciones usan las configuraciones del servidor merge_workload y mutation_workload, respectivamente. Estos valores también pueden anularse para tablas específicas mediante las configuraciones de MergeTree merge_workload y mutation_workload.
planificación de CPU
- Hilo maestro — el primer hilo que empieza a trabajar en una consulta o en una actividad en segundo plano, como una fusión o una mutación.
- Hilo de trabajo — los hilos adicionales que el maestro puede generar para trabajar en tareas intensivas en CPU.
max_threads. En ese caso, las consultas entrantes tendrán que bloquearse y esperar a que haya un slot de CPU para que sus hilos maestro puedan empezar a ejecutarse. Para evitarlo, podría usarse la siguiente configuración:
cpu_slot_preemption. Si está habilitada, cada hilo renueva su slot de CPU periódicamente (según la configuración del servidor cpu_slot_quantum_ns). Esa renovación puede bloquear la ejecución si la CPU está sobrecargada. Cuando la ejecución permanece bloqueada durante un tiempo prolongado (consulte la configuración del servidor cpu_slot_preemption_timeout_ms), la consulta reduce dinámicamente el número de hilos en ejecución concurrente. Tenga en cuenta que la equidad en el tiempo de CPU está garantizada entre cargas de trabajo, pero entre consultas dentro de la misma carga de trabajo podría no cumplirse en algunos casos extremos.
La declaración del recurso de CPU desactiva el efecto de los ajustes
concurrent_threads_soft_limit_num y concurrent_threads_soft_limit_ratio_to_cores. En su lugar, se usa el ajuste de carga de trabajo max_concurrent_threads para limitar el número de CPU asignadas a una carga de trabajo específica. Para lograr el comportamiento anterior, cree únicamente el recurso WORKER THREAD, establezca max_concurrent_threads para la carga de trabajo all con el mismo valor que concurrent_threads_soft_limit_num y use el ajuste de consulta workload = "all". Esta configuración corresponde al ajuste concurrent_threads_scheduler establecido con el valor “fair_round_robin”.Hilos vs. CPU
- Límite del número de hilos:
max_concurrent_threadsymax_concurrent_threads_ratio_to_cores - Limitación de CPU:
max_cpus,max_cpu_shareymax_burst_cpu_seconds
max_threads. La segunda limita el consumo de CPU de la carga de trabajo mediante el algoritmo de cubo de tokens. No afecta directamente al número de hilos, pero sí limita el consumo total de CPU de todos los hilos de la carga de trabajo.
La limitación mediante cubo de tokens con max_cpus y max_burst_cpu_seconds significa lo siguiente. Durante cualquier intervalo de delta segundos, no se permite que el consumo total de CPU de todas las consultas de la carga de trabajo supere max_cpus * delta + max_burst_cpu_seconds segundos de CPU. Limita el consumo medio a max_cpus a largo plazo, pero este límite puede superarse a corto plazo. Por ejemplo, dado max_burst_cpu_seconds = 60 y max_cpus=0.001, se permite ejecutar 1 hilo durante 60 segundos, o 2 hilos durante 30 segundos, o 60 hilos durante 1 segundo, sin que se aplique limitación. El valor predeterminado de max_burst_cpu_seconds es 1 segundo. Valores más bajos pueden provocar un infraaprovechamiento de los núcleos permitidos por max_cpus cuando hay muchos hilos concurrentes.
Mientras mantiene un slot de CPU, un hilo puede estar en uno de estos tres estados principales:
- En ejecución: Consume efectivamente recursos de CPU. El tiempo que pasa en este estado se contabiliza en la limitación de CPU.
- Listo: Esperando a que una CPU esté disponible. No se contabiliza en la limitación de CPU.
- Bloqueado: Realizando operaciones de E/S u otras llamadas al sistema bloqueantes (por ejemplo, esperando un mutex). No se contabiliza en la limitación de CPU.
max_cpu_share, tiene un límite del 70% de los recursos totales de CPU. Por su parte, aunque la ingestión se queda con una garantía de al menos 0.8 * 0.25 = 20%, no tiene límite superior.
Si desea maximizar el uso de CPU en su servidor ClickHouse, evite usar
max_cpus y max_cpu_share para la carga de trabajo raíz all. En su lugar, establezca un valor más alto para max_concurrent_threads. Por ejemplo, en un sistema con 8 CPU, establezca max_concurrent_threads = 16. Esto permite que 8 hilos ejecuten tareas de CPU mientras otros 8 pueden encargarse de operaciones de E/S. Los hilos adicionales generarán presión sobre la CPU, lo que garantiza que se apliquen las reglas de planificación. En cambio, establecer max_cpus = 8 nunca generará presión sobre la CPU porque el servidor no puede superar las 8 CPU disponibles.Reservas de memoria
La planificación de las reservas de memoria es experimental. Solo tiene efecto cuando existe un recurso
MEMORY RESERVATION, y su sintaxis SQL y su comportamiento pueden cambiar en futuras versiones. Aún no es compatible con fusiones ni mutaciones, y la expulsión de una consulta en ejecución se aplica por mejor esfuerzo: surte efecto en el siguiente punto de sincronización de memoria de la consulta, no de forma instantánea.reserve_memory mayor que cero, la asignación se crea en estado pendiente. Una asignación pendiente reserva la cantidad de memoria solicitada en la jerarquía de cargas de trabajo. Si no hay suficiente memoria disponible, la asignación permanece pendiente hasta que se libere suficiente memoria o se expulsen (terminen) otras asignaciones. Cuando una asignación es admitida, pasa a estar en ejecución. Una asignación en ejecución puede aumentar o disminuir su tamaño dinámicamente según el consumo de memoria de la consulta. El ciclo de vida de una asignación puede representarse con el siguiente diagrama de estados:
Las asignaciones pendientes de una carga de trabajo hoja se admiten según el orden FIFO. Cuando varias cargas de trabajo tienen asignaciones pendientes, se admiten según la configuración de precedencia y pesos. Las cargas de trabajo con mayor precedencia se atienden primero. Las cargas de trabajo hermanas con la misma precedencia comparten la memoria según los pesos de forma equitativa max-min, lo que significa que la carga de trabajo con menor uso de memoria normalizado (uso actual más el incremento solicitado, dividido por el peso) se atiende primero. La lógica inversa se aplica durante el desalojo. Cuando es necesario liberar memoria, las cargas de trabajo con menor precedencia y mayor uso de memoria normalizado se desalojan primero.
Tenga en cuenta que los recursos compartidos en el tiempo usan prioridad, mientras que los recursos compartidos en el espacio usan precedencia. Son configuraciones independientes y pueden establecerse con valores distintos. Una prioridad más alta implica apropiación preferente no destructiva (retraso o throttling), mientras que una precedencia más alta puede implicar desalojo destructivo (se detiene con un error). Una carga de trabajo podría tener alta prioridad para la planificación de CPU, pero la misma precedencia para la reserva de memoria, para evitar desalojar otras cargas de trabajo y perder trabajo que estas ya habían realizado.
Toda carga de trabajo con un límite max_memory garantiza que la memoria total asignada en su subárbol no supere ese límite. Si una asignación pendiente o en aumento supera el límite, se inicia el procedimiento de desalojo para liberar memoria. El procedimiento de desalojo selecciona una víctima que se va a terminar. La carga de trabajo ancestro común más bajo del killer y la víctima evita el desalojo en las siguientes situaciones:
- Una asignación pendiente no puede desalojar asignaciones en ejecución dentro de la misma carga de trabajo. (Las cargas de trabajo killer y víctima coinciden).
- Una asignación pendiente de menor precedencia nunca termina una carga de trabajo de mayor precedencia.
- Una asignación pendiente no puede terminar una asignación de la misma precedencia. Tenga en cuenta que las asignaciones en ejecución con la misma precedencia pueden desalojarse entre sí según el uso de memoria normalizado. Si se impide el desalojo o no se libera suficiente memoria, la nueva asignación se bloquea hasta que se libere suficiente memoria. Estas reglas permiten el encolado de consultas excesivas en función de la presión de memoria y proporcionan una forma práctica de evitar errores MEMORY_LIMIT_EXCEEDED.
Los límites de la carga de trabajo son independientes de otras formas de limitar el consumo de memoria, como la configuración de la consulta max_memory_usage. Pueden usarse conjuntamente para lograr un mejor control del consumo de memoria. Es posible establecer límites de memoria independientes por usuario (no por carga de trabajo). Esto es menos flexible y no proporciona funciones como la reserva de memoria y el encolado de consultas pendientes. Consulte sobreasignación de memoria
max_waiting_queries limita el número de asignaciones pendientes para la carga de trabajo. Cuando se alcanza el límite, el servidor devuelve un error SERVER_OVERLOADED. Tenga en cuenta que max_waiting_queries no se hereda en las cargas de trabajo hijas y solo tiene sentido para las cargas de trabajo hoja.
La planificación de la reserva de memoria todavía no es compatible con las fusiones ni las mutaciones.
Solo las consultas con la configuración reserve_memory superior a cero pueden quedar bloqueadas mientras esperan la reserva de memoria. Sin embargo, las consultas con reserve_memory igual a cero también se contabilizan en la huella de memoria de su carga de trabajo, y pueden ser desalojadas si es necesario para liberar memoria para otras asignaciones pendientes o en crecimiento. Las consultas sin la anotación de carga de trabajo adecuada no están sujetas a la planificación de la reserva de memoria y el planificador no puede desalojarlas.
Para proporcionar una reserva de memoria no elástica para una consulta, establezca las configuraciones de consulta reserve_memory y max_memory_usage en el mismo valor. En este caso, la consulta reservará una cantidad fija de memoria y no podrá aumentar su asignación de forma dinámica. Tenga en cuenta que la reserva de memoria elástica puede aumentarse por encima de reserve_memory hasta max_memory_usage sin que la consulta se termine, salvo que haya presión de memoria. Pero no puede reducirse por debajo de reserve_memory incluso cuando el consumo real sea menor.
Veamos un ejemplo de configuración:
Planificación de slots de consulta
max_concurrent_queries limita la cantidad de consultas concurrentes que pueden ejecutarse simultáneamente para una carga de trabajo determinada. Es análoga a la configuración de consulta max_concurrent_queries_for_all_users y a la configuración del servidor max_concurrent_queries. Las consultas con async insert y algunas consultas específicas, como KILL, no cuentan para este límite.
Las configuraciones de carga de trabajo max_queries_per_second y max_burst_queries limitan la cantidad de consultas de la carga de trabajo mediante un limitador de tasa de tipo token bucket. Esto garantiza que, durante cualquier intervalo de tiempo T, no se iniciará la ejecución de más de max_queries_per_second * T + max_burst_queries consultas nuevas.
La configuración de carga de trabajo max_waiting_queries limita la cantidad de consultas en espera para la carga de trabajo. Cuando se alcanza el límite, el servidor devuelve un error SERVER_OVERLOADED. Tenga en cuenta que max_waiting_queries no se hereda en las cargas de trabajo hijas y solo tiene sentido para las cargas de trabajo hoja.
Las consultas bloqueadas esperarán indefinidamente y no aparecerán en
SHOW PROCESSLIST hasta que se cumplan todas las restricciones.Almacenamiento de cargas de trabajo y recursos
CREATE WORKLOAD y CREATE RESOURCE, se almacenan de forma persistente, ya sea en disco, en workload_path, o en ZooKeeper, en workload_zookeeper_path. Se recomienda el almacenamiento en ZooKeeper para garantizar la consistencia entre los nodos. Como alternativa, se puede usar la cláusula ON CLUSTER junto con el almacenamiento en disco.
Cargas de trabajo y recursos basados en la configuración
Formato de la configuración
CREATE WORKLOAD y CREATE RESOURCE. Todas las consultas deben ser válidas.
Recomendaciones de uso
- Definir la carga de trabajo raíz y los recursos de E/S de red en la configuración para establecer los límites de la infraestructura
- Configurar
throw_on_unknown_workloadpara hacer cumplir estos límites - Crear
CREATE WORKLOAD default IN allpara aplicar automáticamente los límites a todas las consultas (ya que el valor predeterminado de la configuración de consultaworkloades ‘default’) - Permitir que los usuarios creen cargas de trabajo adicionales dentro de la jerarquía configurada
Acceso estricto a los recursos
throw_on_unknown_workload. Si se establece en true, cada consulta deberá usar una configuración de consulta workload válida; de lo contrario, se lanzará la excepción RESOURCE_ACCESS_DENIED. Si se establece en false, esa consulta no usará el planificador de recursos; es decir, tendrá acceso ilimitado a cualquier RESOURCE. La configuración de consulta use_concurrency_control = 0 permite que la consulta omita el planificador de CPU y obtenga acceso ilimitado a la CPU. Para imponer la planificación de CPU, cree una restricción de configuración que mantenga use_concurrency_control como un valor constante de solo lectura.
No establezca
throw_on_unknown_workload en true a menos que se haya ejecutado CREATE WORKLOAD default. Esto podría causar problemas durante el inicio del servidor si, en ese momento, se ejecuta una consulta sin la configuración explícita workload.Jerarquía de nodos de planificación
inflight_limit(restricción) - bloquea si el número de solicitudes simultáneas en curso superamax_requestso si su coste total superamax_cost; debe tener un único hijo.bandwidth_limit(restricción) - bloquea si el ancho de banda actual superamax_speed(0 significa ilimitado) o si la ráfaga superamax_burst(por defecto equivale amax_speed); debe tener un único hijo.fair(política) - selecciona la siguiente solicitud que se atenderá de uno de sus nodos hijos según la equidad max-min; los nodos hijos pueden especificarweight(el valor por defecto es 1).priority(política) - selecciona la siguiente solicitud que se atenderá de uno de sus nodos hijos según prioridades estáticas (un valor más bajo significa una prioridad más alta); los nodos hijos deben especificarpriority(el valor por defecto es 0).fifo(cola) - hoja de la jerarquía capaz de contener solicitudes que superan la capacidad del recurso.
limit- garantiza que la asignación total del hijo nunca supere un límite; inicia el procedimiento de desalojo en un subárbol si es necesario; debe tener un único hijo.fair_allocation- aplica el desalojo según la equidad max-min; una asignación pendiente nunca desaloja una asignación en ejecución; los nodos hijos pueden especificarweight(el valor por defecto es 1).precedence_allocation- aplica el desalojo según la precedencia estática (un valor más bajo significa una precedencia más alta); la asignación pendiente de mayor precedencia desaloja las asignaciones de menor precedencia; los nodos hijos deben especificarprecedence(el valor por defecto es 0).queue- hoja de la jerarquía capaz de contener asignaciones en ejecución y pendientes.
Configuración XML en desuso
storage_configuration del servidor:
Para habilitar la planificación de E/S para un disco específico, debe especificar read_resource y/o write_resource en la configuración de almacenamiento. Esto le indica a ClickHouse qué recurso debe usar para cada solicitud de lectura y escritura de ese disco. El recurso de lectura y el de escritura pueden referirse al mismo nombre de recurso, lo que resulta útil para Local SSD o HDD. Varios discos distintos también pueden referirse al mismo recurso, lo que resulta útil para discos remotos si desea permitir un reparto equitativo del ancho de banda de red entre, por ejemplo, las cargas de trabajo de “producción” y “desarrollo”.
Ejemplo:
Véase también
- system.scheduler
- system.workloads
- system.resources
- merge_workload configuración de MergeTree
- merge_workload configuración global del servidor
- mutation_workload configuración de MergeTree
- mutation_workload configuración global del servidor
- workload_path configuración global del servidor
- workload_zookeeper_path configuración global del servidor
- cpu_slot_preemption configuración global del servidor
- cpu_slot_quantum_ns configuración global del servidor
- cpu_slot_preemption_timeout_ms configuración global del servidor