Здравствуйте коллеги!
Заказчик требует реализации метода, который бы выполнял клонирование некоторых записей.
Например:
На примере АЗС
Есть сеть заправок, их количество достигает 61 000 тыс.
Каждая заправка имеет ряд предоставляемых услуг.
Понятное дело, что это продажа разных видов топлива.
У каждой заправки свой перечень видов, это выглядит так:
Заправка А - 17
Заправка Б - 18
INSERT INTO `features` (`id`, `name`, `type`, `value`, `organization_id`) VALUES
	(36, 'Заправка', 'enum', NULL, 17),
	(71, 'Заправка', 'enum', NULL, 18);
INSERT INTO `features_values` (`id`, `feature_id`, `name`) VALUES
	(111, 71, 'Аи-92'),
	(115, 36, 'Аи-95'),
	(113, 36, 'Аи-98'),
	(112, 71, 'Дт');
Заказчик выбирает любую компанию и вносит корректив в перечень текущей компании.
И внимание!  Что бы была опция для распространения корректива на все компании
Например всем 61 000 добавить условно "Пропан"
Для этого я написал функцию, ниже есть её реализация.
$features_repository->cloning($feature->getName(), $item);
Привожу пример функции.
Функция работает корректно, за исключением того, что его некоторая часть, достаточно дорога.
/**
     * @Rest\Route(
     *     path="/features.edit",
     *     methods={"POST"}
     * )
     * @param ObjectManager $manager
     * @param Request $request
     * @param RestMessage $restMessage
     * @return JsonResponse
     * @throws RestException
     * @throws DBALException
     */
    public function edit(ObjectManager $manager, Request $request, RestMessage $restMessage)
    {
        /** @var FeatureRepository $features_repository */
        $features_repository = $manager->getRepository("App:Feature");
        $feature = $features_repository->findOneBy([
                "id" => $request->get("feature_id", 0)]
        );
        if (!is_object($feature)) {
            RestError::exception(RestCode::RECORD_NOT_FOUND);
        }
        
        switch ($request->get("type", false)) {
            case "bool":
            {
                $feature->setType("bool");
                $feature->setName($request->get("name"));
                $feature->setValue($request->get("value"));
                foreach ($feature->getValues() as $value) {
                    $manager->remove($value);
                    $manager->flush();
                }
                $manager->persist($feature);
                break;
            }
            case "text":
            {
                $feature->setType("text");
                $feature->setName($request->get("name"));
                $feature->setValue($request->get("value"));
                foreach ($feature->getValues() as $value) {
                    $manager->remove($value);
                    $manager->flush();
                }
                $manager->persist($feature);
                break;
            }
            case "enum":
            {
                $feature->setType("enum");
                $feature->setName($request->get("name"));
                $feature->setValue($request->get(null));
                /** @var FeatureValue $old_fv */
                $not_persist = [];
                foreach ($feature->getValues() as $old_fv) {
                    $remove_old_fv = true;
                    foreach ($request->get("value", []) as $new_value) {
                        if ($new_value == $old_fv->getName()) {
                            $remove_old_fv = false;
                            $not_persist[] = $new_value;
                            break;
                        }
                    }
                    if ($remove_old_fv) {
                        $manager->remove($old_fv);
                        $manager->flush();
                    }
                }
                foreach ($request->get("value", []) as $item) {
                    foreach ($not_persist as $np) {
                        if ($item == $np) continue 2;
                    }
                    $feature_value = new FeatureValue();
                    $feature_value->setName($item);
                    $feature_value->setFeature($feature);
                    $feature->getValues()->add($feature_value);
                    $manager->persist($feature_value);
                    // Дорогой mysql запрос
                    if ($request->get("cloning", false)) {
                        $features_repository->cloning($feature->getName(), $item);
                    }
                }
                break;
            }
            default:
            {
                RestError::exception(RestCode::REQUEST_WITH_INVALID_PARAMETERS);
            }
        }
        $manager->flush();
        return $restMessage->success("Ok");
    }
Обратите внимание на комментарий  "Дорогой mysql запрос"
Функция клонирования
/**
     * @param string $feature_name
     * @param string $feature_value_name
     * @throws DBALException
     */
    public function cloning(string $feature_name, string $feature_value_name)
    {
        $conn = $this->getEntityManager()->getConnection();
        $sql = "
            INSERT IGNORE INTO    features_values (`feature_id`, `name`)  (
                SELECT DISTINCT   f.id, :feature_value_name
                FROM              features f 
                LEFT JOIN         features_values fv 
                ON                f.id = fv.feature_id  
                WHERE             f.name = :feature_name AND f.`type` = :feature_type 
            );
        ";
        $stmt = $conn->prepare($sql);
        $stmt->execute([
            "feature_type" => EnumFeatureType::ENUM_TYPE,
            "feature_name" => $feature_name,
            "feature_value_name" => $feature_value_name
        ]);
    }
Схема

Самое главное, что таблица 
features_values будет содержать сотни миллионов записей ((
Что делать????
Форкать процесс, пусть себе живет сутки?
Ресурсы:
