shoorick: (Рыжий)
В Open Journal Systems данные людей — пользователей и авторов — могут быть только на одном языке. В багтрекере уже шесть лет висит bug 5598 — allow for author names in multiple languages. В последнем комментарии разработчик честно сообщает:
This hasn't yet been prioritized for a specific release, but I'd say it's very unlikely to be implemented for OJS 2.x; it'll become a higher priority after OJS 3.0 is released.

Итак, OJS 3.0.0 вышла — и действительно, ничего не поменялось: раз эта задача не была приоритетной, то и многоязычности нет.

SQL-запрос

Значит, придётся и дальше поддерживать свой хак, пытаясь всё-таки сделать из него нормальный плагин.

http://shoorick.ru/2016/09/19/ojs-bug-5598-stalled/
shoorick: (Рыжий)
Функция selectall_arrayref перлового модуля DBI хороша для тех, кому лень писать:
This utility method combines "prepare", "execute" and "fetchall_arrayref" into a single call. It returns a reference to an array containing a reference to an array (or hash, see below) for each row of data fetched.

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

Реальный пример: скрипт, извлекающий тайлы из пакета, созданного Тайлмиллом, пытался читать данные как раз функцией selectall_arrayref. Зная, что применяется запрос
SELECT * FROM tiles

и что представление tiles содержит, помимо прочего, содержимое тайлов, занимающее места больше всего остального, нетрудно догадаться, что попытка выполнения запроса потребует выделения памяти в объёме, сопоставимом с размером файла, в котором сидит база (пакет с тайлами — это база SQLite).

Набор тайлов для территории размером 600×400 км в средних широтах — например, с Челябинском по центру, Ашой на западе, Карталами на юге и Тюменью на северо-востоке — займёт больше гигабайта для набора масштабов не больше шестнадцатого. На практике так и получилось: скрипт отжирал больше гигабайта памяти и всё никак не мог приступить к полезной части, пытаясь отожрать ещё. Если же увеличивать масштаб, затраты вырастут ещё сильнее: добавим семнадцатый зум масштаб — понадобятся ещё три-четыре гигабайта, Добавим восемнадцатый, которого хватит даже для любопытных исследователей карт — ещё на десять-двадцать объём вырастет. Если будем сохранять тайлы с глубиной цвета 24 бита, а не восемь — ещё больше места израсходуем. Получается, что средних размеров российская область может занять своими тайлами десятки гигабайт. И скрипт бы безуспешно пытался эти десятки получить.

Переписал:
-my $tiles = $dbh->selectall_arrayref(
-    'SELECT * FROM tiles',
-    { Slice => {} },
-);
-
-foreach my $tile ( @$tiles ) {

+my $sth = $dbh->prepare('SELECT * FROM tiles');
+   $sth->execute;
+
+while ( my $tile = $sth->fetchrow_hashref ) {

и всё наладилось: скрипт перестал жрать память (ему хватило десяти мегабайт) и ждать её выделения — сразу работает.

Вывод: не всегда надо экономить рабочее время программиста — иногда надо и о машинном времени задумываться.

http://shoorick.ru/2015/08/26/more-code/
shoorick: (Default)
Странности творятся. Почитав мануал, обращаюсь к друпаловой БД, ищу дубликаты адресов в таблице с 7500 строками:
SELECT `alias`
FROM `PREFIX_url_alias`
GROUP BY `language`, `alias`
HAVING COUNT(*)>1;
MySQL достаточно резво выдаёт ответ из почти семи десятков строк. Делаю запрос с подзапросом, чтоб выбрать номера узлов с найденными на предыдущем шаге дублями:
SELECT `source`
FROM `PREFIX_url_alias`
WHERE `alias` IN (
    SELECT `alias`
    FROM `PREFIX_url_alias`
    GROUP BY `language`, `alias`
    HAVING COUNT(*)>1
);
В итоге MySQL тяжко задумывается — вот уж 20 минут непонятно, что делает. Посмотрел SHOW CREATE TABLE — по полю `alias` строится индекс. Чё ему ещё надо-то?

P. S. Понятно, что я могу найденное на первом шаге тупо перебрать в цикле, написав какой-нибудь перлоскрипт, однако хочется сделать как-то изящнее.
shoorick: (Default)
Похоже, в друпале придётся применять тот же способ, как и в одном из предшествующих сайтов — отказаться от всяческих абстракций в пользу чистого SQL. Если, конечно, он предусмотрен.

Поглядев статистику потраченного друпалом времени и количества запросов к СУБД, офигел весь был неприятно удивлён: на формирование страницы со списком подмножества опубликованных статей друпал потратил от 100 до 11 тысяч запросов, что заняло от 2 секунд до более чем полутора минут. Это как так?

Я, конечно, понимаю, что время программиста сейчас ценится выше машинного времени плюс друпалу на отрисовку страницы ещё нужны кое-какие ресурсы, но это не может служить оправданием того безобразия, что я наблюдаю: сидя дома, не имея под рукой эпического полотна со структурой хотя бы части БД, я минут за 10 написал и отладил SQL-запрос, который формирует тот же самый список статей и при этом выполнение запроса укладывается в десятки миллисекунд. На то, чтобы понять, как работают Views, и поэкспериментировать с ними, я потратил часы и дни. И всё равно толком не понял.
shoorick: (Default)
Видимо, я ничё не понимаю в ORM вообще и DBIx::Class в частности.
Элементарная для чистого SQL задача: вывести отсортированный по алфавиту список людей может решаться, например, таким запросом:
SELECT CONCAT_WS(' ', lname, fname, sname) AS name
FROM user
ORDER BY name;
Попытки перевести этот запрос на DBIx::Class — сплошь и рядом безуспешные, не помогает ни бубен, ни чтение мануала. Точнее, чтение мануала помогло лишь в одном, понять, что атрибут as ничего не делает. Гугление тоже не особо помогает... По каким принципам в DBIx::Class используются всякие \, [] и {} — тоже не ясно, складывается ощущение, что как попало.

upd/16:50: Из всех методов один даёт почти такой запрос, какой надо. Но как странно это выглядит!
$c->model('Dbase::User')->search(
    {},
    {
        'select'   => [ { '' => \q{CONCAT_WS(' ', lname, fname, sname)}, -as => 'name' } ],
        'order_by' => [ 'name' ],
    }
)
upd/вечернее: Атрибут as всё-таки нужен. Но не для влияния на SQL (он на него не влияет), а для явного указания дбикс-классу имени нового поля.
'select' => [ 'id', { '' => \q{CONCAT_WS(' ', lname, fname, sname)}, -as => 'name' } ],
'as'     => [qw( id name )],
Если его не указать, то появляются сообщение об ошибке: «Метод name не существует».
shoorick: (Default)
Это я такое написал? Проще уж на обычном SQL писать...
$c->stash->{'checkpoints'} = [
    $c->model($MODEL)->search(
        {
            'stgroup_id.id'           => $student->stgroup_id->id,
            'checkresults.student_id' => [ $student->id, undef ],
        },
        {
            'select'   => [ \'me.name cpname', qw/me.id me.date max_ball/ ],
            'join'      => [
                'checkresults', {
                    'tss_id' => [
                        qw/stgroup_id subject_id/,
                        { 'teacher_id' => 'user_id' }
                    ],
                }
            ],
            '+columns'  => [
                qw/subject_id.name checkresults.ball/,
                qw/user_id.fname user_id.sname user_id.lname/,
            ],
#             '+as'       => [ qw/subject_name ball/ ],
            'order_by'  => [ qw/date/ ],
        },
    )
];
shoorick: (Default)
Пытаюсь, по совету коллег-перловиков, разобраться с префетчингом в DBIx::Class.

Тяжко. Мануал и кукбук весьма обрывочны и противоречивы, а программирование методом научного тыка неэффективно — в редкие моменты, когда сервер не падает, среди SQL-запросов появляются более сложные, с джойнами, но и они дублируются, так что общее число запросов не сокращается.

Чё делать? То ли забить (не вариант, ибо в новом году ожидается трёхкратное возрастание нагрузки на сервер), то ли дальше курить маны в ожидании просветления...

Re: Ой

Dec. 7th, 2009 09:52 pm
shoorick: (Default)
Поглядев на терзание сервера баз данных нашей поделкой, решил попробовать другой метод: DBIx::Class, вроде бы, позволяет выполнять произвольный SQL-запрос. Запрос-то я написал и протестировал, да вот подсунуть его каталисту пока не получается...

Пойду-ка домой, ужинать и читать мануалы.
shoorick: (Default)
DBDesigner теперь переименовался в MySQL Workbench, он бесплатный и кроссплатформенный, но самостоятельно соединяться с БД через SSH-туннель пока не научился. Туннель можно прорыть вручную:
ssh -f -L 3307:database.server:3306 gateway.user@gateway.server sleep 60
После чего MySQL Workbench, если в параметрах соединения с БД ему указать Hostname: localhost и Port: 3307, успешно соединяется с базой.

Но вот консольный клиент соединяться не желает:
mysql -P 3307 -u database.user -p database.name
Enter password:
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)
upd/12:51:Если создать сокет вручную:
perl -MIO::Socket -e 'IO::Socket::UNIX->new(Local=>q{/tmp/mysql.3307.sock})'
и указать клиенту флагом -S, что хотим соединятьс именно через этот сокет, он всё равно не соединяется. Меняется лишь код ошибки — (61) вместо (2)

upd/13:17: Если клиенту указать адрес хоста как -h 127.0.0.1 — он успешно соединяется.
shoorick: (Default)
Задавшись целью отслеживать в траке (trac) свежие тикеты (таймлайн для этого не совсем удобен, ибо содержит массу других событий и фиксирует только появление/закрытие/повторное открытие) и комментарии к ним, нашёл механизм: через отчёты.

Сделал три отчёта )

Получил искомое. Доволен.

shoorick: (Default)
Вместо ковыряния в отсутствующей доке найдён более весёлый путь: трафик меж клиентом (готовой гуёвой софтиной) и сервером снюхивается. Например, ызырилом. После чего выясняется, что и запросы и ответы ходят в открытом виде (правда, в разных кодировках, но это уже не важно), после чего наступает Щастье™.

upd: Чтоб не забыть, фильтр:
tds.type == 0x1
оставляет только запросы.
shoorick: (Default)
Путём плясок с бубном, чтения книг и гугления таки наваял искомый скрипт. Попутно выяснил, что толстенная книга по MS SQL Server 6.5, n лет валяющаяся в отделе — с ошибками.
shoorick: (Default)
Оказывается, в MySQL временные таблицы не могут использоваться в одном запросе более одного раза.
А у меня она используется семь раз.
В результате чего мне прилетает Error 1137: Can't reopen table.
Абыдна!

upd: Пришлось создавать семь временных таблиц...
shoorick: (Default)
Хозяйке на заметку:
То, что делается при помощи mysqldump, в ЁМСовом МыМанагере можно сделать так:
Tools / Extract Database... (Инструменты / Извлечь метаданные)
shoorick: (Default)
Новый МыМанагер рулит.
Осталось ещё mysql на сервере заапгрейдить.
Ибо 3.23 устарел нафиг. Народ-то уже пятым пользуется...
shoorick: (Default)
Поставил свежий EMS SQL Manager 2005 for MySQL (он же 3.5.0.5 по привычной нумерации).
Наконец-то наладилась перекодировка между КОИ-8 и Windows-1251.
ЁМСовцы сказали, что проблема была на нашей стороне, ибо начиная с третьей версии перекодировку должен осуществлять не клиент, а сервер.
А не осуществлял! Но теперь — всё хорошо!

Пошёл трудиться...

Итого

Apr. 29th, 2005 07:02 pm
shoorick: (Default)
Два рабочих дня усиленного ковыряния в MSSQL и перле, сопровождающегося напряжением мозгов, подошли к концу.

Краткие выводы:
  1. SQL надо было всё-таки на 4-5 курсе учить, а не сейчас;
  2. SELECT — он и в Африке SELECT
  3. IPSoft (у них даже сайт не работает!) хелп к собственному продукту пишут через... Ну все поняли.

  4. скрипт работает!

P. S. Можно идти отмечать День всемирной солидарности трудящихся.
Ура, товарищи!
shoorick: (Default)
Полдня с сисадмином сочиняем запросы к БД, в которой 184 таблицы.
Крыша уже едет...
shoorick: (Default)
Чтоб самому потом не забыть:
SELECT *,(d2>=d3 AND d1<=d4) AS cmp FROM `test_ival`
Возвращает 1 в случае пересечения диапазонов [d1; d2] c [d3; d4] и 0 в противном случае.
Если вместо >= и <= использовать соответственно > и <, получится проверка пересечения (d1; d2) c (d3; d4).

Profile

shoorick: (Default)
shoorick

December 2016

S M T W T F S
    1 23
45678910
11121314151617
18 19 2021222324
25262728293031

Syndicate

RSS Atom

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jul. 20th, 2017 02:34 pm
Powered by Dreamwidth Studios