Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Find service aggregate virtual columns in SQL
Converts the `aggregate_all_vm_*` virtual_columns to use `arel` when possible. This drastically reduces the number of objects required to be instantiated, records queried against in serial, and time per request on a show page for a Service with a large number of VMs under it. This does so by creating arel functions that perform nested selects to return aggregate data from the VMs and associated hardware and disk relationships. For example: the following ActiveRecord statement: Service.select(:id, :aggregate_all_vm_cpus).first Will generate the following SQL statement: SELECT id, ( SELECT SUM(hardwares.cpu_total_cores) FROM services aggregate_all_vm_cpus_services JOIN service_resources ON service_resources.service_id = aggregate_all_vm_cpus_services.id AND service_resources.resource_type = 'VmOrTemplate' JOIN vms ON vms.id = service_resources.resource_id JOIN hardwares ON hardwares.vm_or_template_id = vms.id WHERE (("aggregate_all_vm_cpus_services"."id" = services.id OR "aggregate_all_vm_cpus_services"."ancestry" ILIKE CONCAT(services.id, '/%')) OR "aggregate_all_vm_cpus_services"."ancestry" = CAST(services.id AS VARCHAR))) AS aggregate_all_vm_cpus FROM services LIMIT 1; And generate no further calls to the DB to return the aggregated data when the `.aggregate_all_vm_cpus` method is called on the returned object. NOTE: These virtual_columns should not be used on more than one record at a time. While this is drastically improves performance when determining the aggregate states for a single record and prevents instantiating unnecessary objects to built these aggregations, this is still technically an N+1 query. The nested selects will be performed individually for each service record returned, and can become expensive quickly.
- Loading branch information