Ответы пользователя по тегу MySQL
  • MYSQL на SSD оптимизация?

    65536
    @65536
    query_cache_type = 1

    там myisam что ли? если да, и если таблицы большие, то надо менять на иннодб. кэш этот вырубать, тормозов от него больше чем пользы, особенно когда много записи идет. потом в зависимости от размера оперативки подобрать значения иннодбшных параметров

    меня вот эта статья спасла https://ruhighload.com/%D0%9E%D0%BF%D1%82%D0%B8%D0...

    для 8 гб выглядит так

    innodb_buffer_pool_size = 4G
    innodb_log_file_size = 512M
    innodb_buffer_pool_instances = 4

    innodb_flush_log_at_trx_commit я поставил 0, так быстрее всего но типа ненадежно, но незнаю где там эта грань надежности и как надо базу нагрузить чтоб проломить эту грань, никаких проблем с данными больше чем за год не случилось.
    https://ruhighload.com/innodb_flush_log_at_trx_com...

    думаю что всё очень индивидуально, зависит от кол-ва столбцов и их типов, но от маисама лучше уходить. он начинает конкретно тормозить на таблицах от каких-нить 100к записей. перед уходом желательно убедиться не используются ли в нем какие то фичи которые еще не появились в иннодб. начиная с 5.7 вроде ничего такого не осталось. до неё были различия в работе с переменными

    майсклтюнер дал не самые лучшие советы кстати, но близкие
    Ответ написан
  • Как импортировать большие файлы xlsx частями?

    65536
    @65536
    https://github.com/box/spout вот правильная библиотека, жрет мегабайта 2 независимо от размера файла
    Ответ написан
  • Насколько сильная разница между запросами * и `id` в MySQL?

    65536
    @65536
    сильно будут отличаться если выбираются текстовые поля с длинными текстами
    Ответ написан
  • Дерево категорий Laravel. Как уменьшить количество запросов в БД?

    65536
    @65536
    Раньше тоже так делал (обычный AL и запросы к бд рекурсивно). На километровом дереве начались тормоза. Переделал на однозапросный вариант, как уже советовали. На практике оказалось, что тормоза были не из-за этого, а из-за рендрежки дерева. На сервере с настроенным mysql_cache и редко меняющейся таблице категорий разница между 1 и 200 запросами оказалась ерундовой, но она есть. + кому-то "повезёт" подождать дерево когда кэш сбросится.

    Приложу свой вариант (как раз для элоквента), два класса, сложите куда-нибудь и переименуйте как вам надо.

    class Tree
    {
        private $builder;
    
        private $parentIdFieldName = 'parent_id';
    
        private $nodesById = [];
        private $nodesByParent = [];
    
        public function __construct($builder)
        {
            $this->builder = $builder;
        }
    
        public function parentIdField($name)
        {
            $this->parentIdFieldName = $name;
    
            return $this;
        }
    
        /**
         * @return Output
         */
        public function get()
        {
            $nodes = $this->builder->get();
    
            foreach ($nodes as $node) {
                $this->nodesById[$node->id] = $node;
                $this->nodesByParent[$node->{$this->parentIdFieldName}][] = $node;
            }
    
            $output = new Output;
    
            $output->parentIdFieldName = $this->parentIdFieldName;
            $output->nodesById = $this->nodesById;
            $output->nodesByParent = $this->nodesByParent;
    
            return $output;
        }
    }

    class Output
    {
        public $parentIdFieldName = 'parent_id';
    
        public $nodesById = [];
        public $nodesByParent = [];
    
        public function getNode($id)
        {
            if (!isset($this->nodesById[$id])) {
                $this->nodesById[$id] = [];
            }
    
            return $this->nodesById[$id];
        }
    
        public function getSubnodes($id)
        {
            if (!isset($this->nodesByParent[$id])) {
                $this->nodesByParent[$id] = [];
            }
    
            return $this->nodesByParent[$id];
        }
    
        private $branch;
    
        public function getBranch($id))
        {
            if (isset($this->nodesById[$id])) {
                $this->branch = [];
                $this->branchRecursion($id);
    
                return array_reverse($this->branch);
            }
        }
    
        private function branchRecursion($id))
        {
            $this->branch[] = $this->nodesById[$id];
    
            if ($this->nodesById[$id][$this->parentIdFieldName] > 0) {
                $this->branchRecursion($this->nodesById[$id][$this->parentIdFieldName]);
            }
        }
    }


    На вход надо подать билдер запроса, можно отфильтровать по каким-то критериям (видимость, например), отсортировать, приделать жадные загрузки и тд. Нельзя ограничивать по родительской категории, то есть никак нельзя таким способом взять поддерево определенного узла, это минус такого способа.

    На выходе можно получить модель по ее ид ($tree->getNode($id)) и массив вложенных моделей модели с таким-то ид ($tree->getSubnodes($id)). Можно еще ветку получить - $tree->getBranch($id) выдаст массив моделей от корневой до той у которой ид = $id. Хлебные крошки рисовать чтобы, например

    Вакуумный пример с вашей таблицей. Блейдом не пользовался, но думаю можно ему массив какой то дать или как там делается
    class Test
    {
        private $tree;
    
        private $output;
    
        public function treeView()
        {
            $builder = new ProductCategory; // тут можно дописать что-нибудь типа orderBy('position') или where('enabled', true); главное так чтобы любые ограничения в первую очередь исключали вышестоящие узлы (ни в коем случае не исключали нижестоящие не исключая нижестоящие), иначе дерево получится кривое - недостаток способа
    
            $this->tree = (new Tree($builder))->get();
    
            $this->treeRecursion(0); // здесь уже можно указать ид корневого узла для дерева на выходе
    
            return implode('<br>', $this->output);
        }
    
        private $level = 0;
    
        private function treeViewRecursion($id)
        {
            $node = $this->tree->getNode($id);
            $subnodes = $this->tree->getSubnodes($id);
    
            $this->output[] = str_repeat('--', $this->level) . ' ' . $node->name;
    
            if ($subnodes) {
                $this->level++;
    
                foreach ($subnodes as $subnode) {
                    $this->treeViewRecursion($subnode->id);
                }
    
                $this->level--;
            }
        }
    }
    
    print (new Test)->tree();


    По-хорошему лучше вообще хранить хтмл кэш готового дерева и заменять его после каждой операции над ним
    Ответ написан
  • Качество кода в компонентах битрикса?

    65536
    @65536
    максимально компактно: разработка на битриксе - это пи-ц
    Ответ написан
  • Как сделать обратную связь модели на саму себя в Eloquent Laravel?

    65536
    @65536
    сделать второй метод (придумайте как назвать)

    public function excludes2()
    {
    return $this->belongsToMany(Category::class, 'excludes_cetegories', 'exclude_id', 'category_id');
    }
    Ответ написан
  • Как сделать меню с категориями?

    65536
    @65536
    хранить где-то в сессии состояние развернутости узлов, массив из идов. решить какое дефолтное состояние для всех, при рендрежке меню учитывать наличие ида в этом массиве, если есть то считать состояние противоположным дефолтному. если выходит что вложенное дерево скрыто, то не рендрить его вообще либо сделать скрытым. при нажатии на узлы слать на сервер инфу о том что такой-то узел меняет состояние, изменить его в сессии (убрать или добавить в тот массив), перезагрузить дерево. или не перезагружать? а джсом его складывать раскладывать, при условии что оно было целиком загружено, вместе со скрытыми узлами

    и только не id_parent, а parent_id
    Ответ написан
  • Что логичней будет, сериализация или в новой таблице?

    65536
    @65536
    битрикс - днище технологий. на заверения сектантов можно не обращать внимания, в диалоги не вступать.

    кто удалит мой ответ - будет заживо сварен в битриксе
    Ответ написан
  • Какую выбрать схему хранения объектов?

    65536
    @65536
    на днях доделал такой сайт. ломание головы остановилось на eav с несколькими типами полей

    вот как получилось
    объявления
    f1bc0bc3600979af86b4cfbf448642f6.png
    категории объявлений
    f7987ad4cb33f257c4b867e1d6841a14.png
    общие поля для объяв из всех категорий
    62102cd79000c00d74d4835868272352.png
    свойства категорий
    7d575bca3a46792ca52094fcbb294546.png
    значения свойств для объявлений
    58517b28450b090220a79838bd750712.png

    основной косяк еава это то что невозможно выбрать одним запросом в зависимости от настроек фильтра, приходится по каждому параметру собирать айдишники и потом их интерсектить, примерно так
    private function get_offers($page, $per_page)
    {
        $filter_fields = $this->get_current_filter_enabled_fields();
        $filter_values = $this->s('@filter~:values_by_cats/' . $this->cat->id);
    
        //
    
        $offers_ids_sets = array();
        $offers_extra_ids_sets = array();
    
        if ($filter_values) {
            foreach ($filter_values as $field_id => $data) {
                if (isset($filter_fields[$field_id])) {
                    $field = $filter_fields[$field_id];
    
                    $prop = $field['prop'];
                    $common_prop = $field['common_prop'];
    
                    if ($prop) {
                        $type = $prop['type'];
    
                        if ($type == 'bool' && $data['value']) {
                            $offers_ids_sets[] = PropValue::where('prop_id', $prop['id'])
                                    ->where('bool_value', true)
                                    ->lists('offer_id')->toArray();
                        }
    
                        if ($type == 'strings_list' && isset($data['selected']) && !is_null($data['selected'])) {
                            $prop_settings = _j($prop['settings']);
    
                            if (isset($prop_settings['strings_list']['items'][$data['selected']])) {
                                $offers_ids_sets[] = PropValue::where('prop_id', $prop['id'])
                                        ->where('string_value', $prop_settings['strings_list']['items'][$data['selected']])
                                        ->lists('offer_id')->toArray();
                            }
                        }
    
                        if ($type == 'numbers_list' && isset($data['selected']) && !is_null($data['selected'])) {
                            $prop_settings = _j($prop['settings']);
    
                            if (isset($prop_settings['numbers_list']['items'][$data['selected']])) {
                                $offers_ids_sets[] = PropValue::where('prop_id', $prop['id'])
                                        ->where('number_value', $prop_settings['numbers_list']['items'][$data['selected']])
                                        ->lists('offer_id')->toArray();
                            }
                        }
    
                        if (($type == 'numbers_list' || $type == 'number') && isset($data['min']) && isset($data['max'])) {
                            $offers_ids_sets[] = PropValue::where('prop_id', $prop['id'])
                                    ->where('number_value', '>=', $data['min'])
                                    ->where('number_value', '<=', $data['max'])
                                    ->lists('offer_id')->toArray();
                        }
                    }
    
                    if ($common_prop) {
                        $type = $common_prop['type'];
    
                        if (($type == 'numbers_list' || $type == 'number') && isset($data['min']) && isset($data['max'])) {
                            $offers_ids_sets[] = OfferExtra
                                    ::where($common_prop['field'], '>=', $data['min'])
                                    ->where($common_prop['field'], '<=', $data['max'])
                                    ->lists('offer_id')->toArray();
                        }
                    }
                }
            }
        }
    
        $offers_ids = array();
    
        if ($offers_ids_sets) {
            $offers_ids = (array)$offers_ids_sets[0];
    
            for ($i = 1; $i < count($offers_ids_sets); $i++) {
                $offers_ids = array_intersect($offers_ids, (array)$offers_ids_sets[$i]);
            }
        }
    
        //
    
        $builder = $this->cat->offers();
    
        if ($offers_ids_sets) {
            $builder = $builder->whereIn('id', $offers_ids);
        }
    
        $builder = $builder->whereHas('extra', function ($builder) use ($offers_extra_ids_sets) {
            $builder->where('enabled', true);
        });
    
        $count = $builder->count();
    
        $offers = $builder->orderBy('created_at', 'DESC')->offset(($page - 1) * $per_page)->take($per_page)->get();
    
        return array($count, $offers);
    }

    и вообще никак невозможно сортировать по параметрам, если нужна сортировка по какому-то параметру придется переносить ее в таблицу товаров самих

    но все равно по гибкости он выигрывает у остальных вариантов. клиент сам через интерфейс может рулить своими категориями свойствами и тд. если бы была таблица в которой всё, она бы вешалась при каждой такой операции, на время пропорциональное кол-ву товаров
    Ответ написан
  • Как сделать ACL для пользователей?

    65536
    @65536
    я делал permissions <-> groups <-> users, где "<->" связь много ко много. потом еще приделал связь permissions <-> users для персонального отбирания/давания разрешения пользователю каких-то разрешений поверх того, что присваивается ему через группы. там где нужно проверить какое-то разрешение, там оно и проверяется. так же разрешения и группы можно связывать с какими-то другими объектами в системе, чтобы владельца обозначить и проверять принадлежность когда надо тоже
    Ответ написан
  • Загрузка excel в базу mysql на laravel, как загрузить большой объем данных?

    65536
    @65536
    Недавно к проекту, которым занимаюсь, заказывали у другого человека парсер, который на входе получал хлсх файлы, потом в порядке очереди сканировал каждый файл, лез на сайт жертву, парсил значения и создавал новый такой же файл с новыми значениями. Сначала он применил PHPExcel, естественно всё загибалось почти сразу же. Грузит в память целиком, и не высвобождает как его не ансетить и дестроить. С каждым файлом оперативки становится заметно меньше, файл на 5 мб превращается в 200 в памяти. В общем не прокатило и он прикрутил вот это https://github.com/box/spout

    там все минимум кода считывается и никаких проблем с памятью. https://github.com/box/spout#reader

    а так приходилось в TSV переводить и его построчно считывать, потому-что ни одной нормальной либы для экселя не было

    если операция одноразовая можно лоад дата инфайл применить, как посоветовали
    Ответ написан
  • Как сбросить id AUTO_INCREMENT, PHP, MYSQL?

    65536
    @65536
    Представьте что за чушь в таблице творится создается новая запись и она под числом 256:


    самая обычная чушь, на которую не стоит и вообще нельзя обращать внимания

    идентификаторы нужны для связей и обращения к записям, а не для красоты. если ими рулить вручную можно запороть связи. если нужно для красоты, сделайте отдельное поле
    Ответ написан
  • Как удалить повторяющиеся значения из массива?

    65536
    @65536
    $has = array();
    $output = array();
    
    foreach ( $input as $data )
    {
        if ( !in_array($data['clothes_name'], $has) )
        {
            $has[] = $data['clothes_name'];
            $output[] = $data;
        }
    }
    Ответ написан
  • Как оптимальнее удалить все файлы, не упоминающиеся в БД?

    65536
    @65536
    Самому надо на днях это будет делать. Думаю сделать влоб так как это однократная операция. Может быть порезче получится если составить два списка. В одном имена картинок в папке, в другом имена картинок из базы. Вычесть из первого списка второй - получится список картинок, которые надо удалить
    Ответ написан
  • Как получить данные трёхмерным массивом?

    65536
    @65536
    в элоквенте для этого есть удобная фича laravel.com/docs/4.2/eloquent#eager-loading

    если вручную, то нужно делать 2 запроса. SELECT * FROM menus и SELECT * FROM menu_items. 2-й можно ограничить WHERE menu_id IN(идишники из результатов первого). Потом 2й нужно в цикле проиндексировать по menu_id, то есть сделать такой массив чтоб его индексы были идшниками из результатов первого, а элементы массивами со строками из результатов 2-го для соответствующих menu_id.

    а при выводе уже просто по ид достаете из 2 го массива

    но может есть вариант поизящней))
    Ответ написан
  • Как дать id форме оплаты?

    65536
    @65536
    ид нужно привязывать не к пользователю а к объекту оплаты, заказу например. у всех систем оплаты примерно одинаковая схема. отсылается форма с данным, среди них идет идентификатор заказа. и еще идет секретная подпись сформированная на основании некоторых данных из формы по заданному системой алгоритму . ПС проверяет верна ли подпись (чтобы не подделывали платежи) если да, то предлагает пользователю варианты оплаты, он уже там все оплачивает и система отвечает вашему сайту запросом об успешности операции и опять так же подписанным (чтобы в вашем сайте не подделывали оплаченность)

    вот в 2 картинках на примере робокассы (сорри за говнокод)

    отправка
    ca61848fedd249d2877718a2a5c2b44c.png
    получение
    a94af4ca35b44b0aa83f2b1554a5565a.png
    Ответ написан