• Копирование большого объёма данных из одной таблицы в другую

    @balloon
    У нас похожие задачи с сравнимым объемом данных. SELECT + LOAD на InnoDB занимает минуты (SSD + ~120Gb RAM). Ключи не отключаем, как и autocommit - имхо при атомарных запросах смысла в этом нет, индексы и так будут обновлены только после окончания записи всех данных. Делаем LOAD IGNORE что бы игнорить дубликаты. Еще одно переимущество SELECT + LOAD перед SELECT INSERT - отсутствие блокировки на время SELECT.
    Ответ написан
    Комментировать
  • Yii: выбор сценария в зависимости от операций в RBAC?

    @balloon
    Если Вам действительно нужна поддержка нескольких сценариев в одной форме, то имхо проще будет добавить поддержку такой фичи в нужной модели (или базовом классе).

    По сути нужно переопределить метод getValidators() и добавить методы для формирования массива сценариев.
    Ответ написан
    1 комментарий
  • Из git в svn, или работа одновременно

    @balloon
    Ответ написан
    Комментировать
  • Алгоритм для поиска номера по маске

    @balloon
    Не придумал как сделать через одну регулярку, но можно попробовать следующее:

    1. Сгенерировать общую регулярку.
    Для 911-AAA-X-BBB это будет выглядеть как 911-(000|111|222|...|999)-[0-9]-(000|111|222|...|999)

    2. Сделать сравнение блоков A,B,C,D через подстроки.
    Для 911-AAA-X-BBB это будет выглядеть как SUBSTRING(phone,5,3) != SUBSTRING(phone,11,3)
    Ответ написан
    5 комментариев
  • Публикация сайта по FTP?

    @balloon
    Когда-то давно я тоже заливал файлы проекта по фтп (до svn, git). Для того что бы ускорить этот процесс у меня было два php файла. Один у меня, который зиповал проект, один на сервере, который его распаковывал. Работало быстрее, чем загрузка по одиночным файлам + всегда была увереность, что все обновления залиты.
    Ответ написан
    Комментировать
  • Как правильно спроектировать БД для френдленты?

    @balloon
    Мы делали опираясь на второй вариант, при этом id друзей кэшировали (т.е. в итоге был простой запрос вида select * from feed where author_id in (1,2,3). И всё было просто до следующих требований:
    1. Нужно было выводить только те записи друга, которые создали после добавления друга (от этого в последствии отказались из-за чрезмерного оверхеда и сомнительной выгоды)
    2. Если кто то из твоих друзей откомментил пост — то он должен был поднятся наверх (упростли до требования поднимать вверх сообщение если хоть кто то его откомментил. Как результат просто ввели еще одно поле с датой апдейта и сортировали по нему)
    3. Приватность для записей, которые ссылаются на другую запись. Вроде Твой дружище лайкнул пост своего друга, который не твой друг. В этом случае если оригинальный пост доступен только для друзей(а вы с ним не друзья), то его не нужно было показывать. (В данном случае автором оставлася всегда оригинальный автор, а сообщение помечалось как ссылка и юзера, который его ретвитил мы записывали в отдельное поле).

    Были и специфичные требования:
    1. Юзера можно было поставить игнор на N дней. В течении этого времени его сообщения должны были игнорирваться.
    2. Пост можно было пометить как избранный, и он постоянно висел в топе (нужно было для мониторинга)

    P.S. кстати в первом варианте выгоднее создать 2 таблицы. Одна — с сообщениями. Вторая EventId,UserId.
    Ответ написан
    2 комментария
  • А как Вы осуществляете взаимодействие модели на стороне сервера с клиентской?

    @balloon
    верстка: если существует вероятность того, что дизайнер будет завязываться на id/class, то Вам следует завязываться на аттрибуты, которые дизайнер точно не должен менять. Для input — это аттрибут name, тогда селектор будет вида $('input[name="login"]'). Для div и подобных можно привязываться к недизайнерским классам + подселекторы.

    server — javascript : я за json в ответах :) поэтому я бы с сервера присылал json вида {login: 'habr', field: 'value'} и на клиентской стороне обходил его и апдейтал присланые поля $('input[name="' + field + '"]').html(value)
    Ответ написан
  • Как подружить .toLowerCase() и null?

    @balloon
    Можно еще переопределить нативную функцию.

    var nativePrompt = prompt;
    var prompt = function(msg) {
        return nativePrompt(msg) || '';
    }
    
    console.log(prompt('Username:').toLowerCase())
    
    Ответ написан
    Комментировать
  • Как хранить архив sql-запросов с тегами для поиска?

    @balloon
    А почему не хранить аналитические запросы тоже в базе данных? Прикрутить к ним тегирование и сделать простой удобный навигатор/редактор/билдер.
    Ответ написан
  • Как выполнить множество SELECT в одной хранимой процедуре?

    @balloon
    Вот пример функции для нахождения id корневой категории
    CREATE DEFINER=`root`@`localhost` FUNCTION `FIND_CATEGORY_ROOT_ID`(category INT) RETURNS int(11)
        DETERMINISTIC
    BEGIN
    	DECLARE root INT;
    	WHILE category IS NOT NULL DO
    		SET root = category;
    		SELECT parent_id INTO category FROM tree WHERE id = category;
    	END WHILE;
    	RETURN root;
    END
    
    Ответ написан
  • Как правильно спроектировать БД MySQL?

    @balloon
    Внесу и свою лепту. Я бы:
    1. Отказался от сокращенного найменования полей и назвал бы некоторые поля по другому bid -> blog_id, uid -> user_id, uid_add -> created_by, uid_upd -> updated_by, time_add -> created_at, url_name -> slug
    2. Объединил таблицы post, special, special_page, news (и соотв. вместо 2 таблиц news_tag & post_tag осталась бы одна) + как уже упомянули, решился бы вопрос с комментариями
    3. Для статуса использовал бы ENUM вместо INT(1), а если ENUM нельзя — то хотя бы TINYINT :)
    4. Если комментариев много — то использовал бы nested set либо добавил поле с путем для быстрого вывода дерева (в чем поле level не помогает вроде)
    Ответ написан
    2 комментария
  • Текстовое поле не хочет быть null?

    @balloon
    Ошибки бросает MySQL. Проверьте, что в таблице не стоит NOT NULL для этих полей.
    Ответ написан
    5 комментариев
  • Как обновить страничку, получаемую при помощи подгрузки ajax`ом?

    @balloon
    var tabs = {
    
        autorefresh: {
            page1: 15, // обновляет табу `page1` каждые 15 секунд
            page2: 30
        },
    
        timers: {},
    
        /**
         * Отображаем табу и сразу же подписываем ее на автообновление если оно для нее предусмотрено
         * @param tabName
         */
        show: function(tabName) {
            $.post("include/"+name+".php", function(content) {
                // @todo Еже ли есть автообновление то думаю нужно кешить контент и обновляеть его только по таймауту
                $('#content').empty().html(content);
                // reschedule autorefresh
                tabs.scheduleAutorefresh(name);
            });
        },
    
        /**
         * Делаем рефреш страниц
         * @param tabName
         */
        scheduleAutorefresh: function(tabName) {
            // если у нас есть не отработаный таймаут для этой табы, то его нужно очистить перед тем как создавать новый
            if (typeof(tabs.timers[tabName]) !== 'undefined')
                clearTimeout(tabs.timers[tabName]);
    
            // проверяем есть ли автообновление у табы
            if (typeof(tabs.autorefresh[tabName]) !== 'undefined') {
                tabs.timers[tabName] = setTimeout(function() {
                    tabs.show(tabName);
                }, tabs.autorefresh[tabName] * 1000);
            }
        },
    
        /**
         * Тут мы показываем дефолтную табу при загрузке страницы
         * + Можем подписать некоторые табы на автообновления (даже если пользователь еще ни разу их не открыл)
         * @param defaultTab
         */
        init: function(defaultTab) {
            tabs.show(defaultTab);
    //        $.each(tabs.autorefresh, function(tabName) {
    //            tabs.scheduleAutorefresh(tabName);
    //        });
        }
    };
    
    tabs.init('defaultTabName');
    
    Ответ написан
  • Почему mySQL постоянно уходит в swap?

    @balloon
    Исходя из Innodb_buffer_pool_pages_free = 0 предположу, что следует увеличить innodb_buffer_pool_size.
    Ответ написан
  • Помогите составить 2 SQL-запроса

    @balloon
    -- checked on 4M rows
    
    CREATE TABLE `test` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `company` int(11) NOT NULL,
      `customer` int(11) NOT NULL,
      `item` int(11) NOT NULL,
      PRIMARY KEY (`id`),
      KEY `search` (`company`,`customer`,`item`)
    ) ENGINE=MyISAM AUTO_INCREMENT=4000001 DEFAULT CHARSET=utf8;
    
    -- 1) ~ 2.2sec
    SELECT company, count(customer) as `customers_count`
    FROM (SELECT customer, company FROM test GROUP BY customer HAVING COUNT(DISTINCT item) > 5) as `temp`
    GROUP BY company
    ORDER BY customers_count DESC
    LIMIT 100
    
    -- 2) ~2.2sec
    
    SET @rank = 0;
    SELECT rank, company FROM (
    	SELECT @rank := @rank + 1 as `rank`, company FROM (
    		SELECT company, count(customer) as `customers_count`
    		FROM (SELECT customer, company FROM test GROUP BY customer HAVING COUNT(DISTINCT item) > 5) as `temp`
    		GROUP BY company
    		ORDER BY customers_count DESC
    		LIMIT 100
    	) as `temp2`
    ) as `temp3`
    WHERE company = 159
    
    
    Ответ написан
    3 комментария
  • Обновление пароля пользователя в Yii

    @balloon
    public function beforeSave() {
      if ($this->isNewRecord)
         $this->password = md5($this->password);
      return parent::beforeSave();
    }
    
    Ответ написан
    Комментировать
  • Добавление больших объемов данных в MySQL из Node.JS

    @balloon
    Видимо lazy грешит утечкой памяти. Попробуйте написать свой обработчик для stream.on('data',… ), который будет разбивать блоки текста на строки и сразу же их обрабатывать. Пример можно посмотреть здесь: github.com/j03m/node-csv2xml/blob/master/lineByline.js. В итоге получите контроль над использованием памяти.
    Ответ написан
    Комментировать
  • Как в php отделить объявление класса от его реализации?

    @balloon
    Мне кажется, что:
    1. В итоге Вы придете к абстрактному классу
    2. Все таки придеться создать dependency container, если вы не хотите что бы родительский класс знал о наследниках.

    abstract class DataKeeper {
      protected $data;
    
      public function setData($data) {
        $this->data = $data;
      }
    
      public function getData() {
        return $this->data;
      }
    
      abstract public function save()
      
      abstract public function process()
    }
    
    class FileDataKeeper extend DataKeeper {
    
      public function save() {
        // implementation
      }
    
      public function process() {
        // implementation
      }
    }
    
    class Container {
      protected static $classes = array();  
    
      public static function register($alias, $class) {
        self::$classes[$alias] = $class;    
      }
    
      public static function get($alias) {
        if (!isset(self::$classes[$alias]))
    	throw new Exception("...");      
    
        $className = self::$classes[$alias];
        return new $className();
      }
    }
    
    
    // bootstrap.php
    Container:register("dataKeeper", "FileDataKeeper");
    
    // SomeWhere.php
    $dataKeeper = Container::get("dataKeeper");
    
    Ответ написан
    Комментировать