Обновить
16
0

Пользователь

Отправить сообщение
1) Я говорю про вставку из временной таблицы в целевую таблицу — сделать там /*+ append*/
Кстати, при использовании процедуры, которая бы на месте вставляла бы сразу в целевую таблицу, пришедшие через параметр PL/SQL table данные, то гоняние данных из пустого в порожнее (использование temp table) можно было бы вообще избежать. минус undo/redo/temp, лишнее вычитывание — это всё время, снова таки.
3) Стоп-стоп-стоп, какие миллионы стейтов?
Вы вставляете данные из таблицы A (test_data) и E (test_state):
   insert into test_history(id, device_id, parameter_id, value, event_date)
      select test_history_seq.nextval, a.device_id, a.parameter_id, e.value, e.last_date
      from   test_data a  
      inner  join test_device b on ( b.id = a.device_id )  
      inner  join test_parameter c on ( c.id = a.parameter_id ) 
      inner  join test_parameter_type d on ( d.id = c.type_id and d.name = 'uptime' )
      left   join test_state e on ( e.device_id = a.device_id and 
                                    e.parameter_id = a.parameter_id )
      where  e.value > a.value;

Зачем вы сюда join-ине таблицы b, c и d если вы их потом нигде не используете? Пустая трата ресурсов, если это не способ отфильтровать входящие данные по параметру uptime? Но и в этом случае, думаю, этот запрос можно было бы написать сильно оптимальнее, особенно учитывая что вы боретесь за доли секунды.
И, снова таки, не надо было его пускать в один поток с критической по производительности вставкой (я вообще всё ещё за выпиливание этой temp таблицы здесь. Не нужна она. Под слоганом, что temp table якобы не пишет undo/redo её сюда втулили ни к селу ни к городу. Субъективно. Пишите сразу в целевую таблицу. Хотите чтобы писалось по минимуму журналирования — покурите nologging и direct path write… впрочем при наличии индексов и внешних ключей ( не дай бог ещё и триггеров), direct path write Вам, увы, не светит).

1) «пренебрежимо мал», когда мы говорим про время на операцию, в среднем меньшее чем 1 десятитысячная секунды? Любопытно. См. выше — четверть мегабайта на 90000 записей с единственным integer полем. С такими пренебрежениями можно вообще об оптимизации не заботится.
2) На счёт soft parse, вы правы только отчасти. В рамках цикла, разбираться не будет. Цикл отрабатывает секунду. Потом начинается новая итерация (или ваши датчики работают только секунду?). На новой секунде вы получите новый prepareCall вызов и новый soft parse. Тобишь по разбору в секунду. А оно вам надо?
3) В этом я вас совсем не понимаю. просто ради интереса померяйте. Возможно сильно удивитесь сколько «едят» ваши констрейнты. Ещё раз — если очень беспокоитесь за то, что с датчика могли прийти данные, которые не ложатся на вашу схему данных — сделайте job, который будет проверять ваши данные и «вычищать» или помечать кривые данные. Можете пояснить зачем вам FK? Вы не уверены в тех данных, что вы вставляете или боитесь что прийдёт другой юзер и навставляет что-то кривое? Зачем на каждой вставке тратить ресурсы на валидацию?
6) Так о что грешен? Это был вопрос, как бы, а не утверждение, что у вас точно плохо всё. Я не знаю как у вас настроена база. Просто проверьте.
7) Неужели построчно выбираете данные, которые ломятся со скоростью порядка 8000 строк в секунду?
8) не совсем. Одно другому не мешает. Тем более что не вижу у вас в джаве распараллеливания потоков. Если бы у вас один поток вставлял данные bulk-ами, а другой собирал новый массив на вставку — это был бы один вопрос. А так, в вашем примере, выполнение последовательно. Соответсвенно формирование нового набора данных будет ожидать возвращения COMMIT-a. Конечно, сделав коммиты реже вы уменьшили влияние, но не отменили его совсем.
9)

Ну… это уже зависит от того у кого какое железо. Может у человека на виртуалке сильно ограниченной всё это запускалось.
А делать так, всё-же, действительно не стоило, как он написал в разделе «не надо так делать». Ну, если производительность вставки действиетльно дорога. Особенно seqences на триггерах, hard-parses и пр. пр. пр. В общем начало темы правильное у него… только продолжать ещё можно много.
PS: в качестве доказательств своих слов про Redo:
CREATE GLOBAL TEMPORARY TABLE tmp_1 (ID INTEGER) ON COMMIT PRESERVE ROWS;
set autotrace on
SQL> INSERT INTO tmp_1 SELECT ROWNUM FROM dba_objects;
90829 rows created.
Statistics
----------------------------------------------------------
        838  recursive calls
       1060  db block gets
       3917  consistent gets
          6  physical reads
     255720  redo size
        573  bytes sent via SQL*Net to client
        527  bytes received via SQL*Net from client
          3  SQL*Net roundtrips to/from client
         59  sorts (memory)
          0  sorts (disk)
      90829  rows processed

Обращаю внимание на redo size.
Если у Вас RAC — то очень влияют. В данном случае — слабо, но тоже влияют.
PS: Ещё по ускорению savedata процедуры:
— Можно воспользоваться /*+ append */ и nologging
— Можно у seqence поднять значение cache (хотя в случае не-RAC системы это поможет в меньшей мере)
— Зачем в savedata Join-ится ряд таблиц я так и не понял, если честно. join-ится практически вся схема, а используются только данные из таблиц с алиасами A и E. То ли я что-то пропустил, то ли вы теряете время на этом.
— В идеале вообще избавится на этом этапе от join-ов и заливать данные как есть. На join-ах теряете время.
— первый и второй insert отличаются двумя условиями. Думаю что можно было бы переписать через insert into ALL WHEN — тоже вероятно ускорило бы.
Добрый день. Тема поднята хорошая. Есть ряд правильных моментов, но есть что добавить. Мне приходилось задаться вопросом потокового сохранения данных с датчиков. Ряд мест где вы, на мой взгляд, не правы или имеете ещё возможности к ускорению.
1) Redo в случае с temporary таблицами тоже пишется, увы. Хоть и меньше. Но это мелочи.
2) Чтобы уменьшить количество soft-parse, можно воспользоваться dbms_sql, создать единождый курсор, отпарсить его текст, а он у вас один и тот же всегда: (insert into ...). И просто подменяя значения bind переменных execute его с новыми значениями. Тем самым вы избавитесь даже от soft parse, которые хоть и легче, но всё равно ресурсоёмкие.
3) Constraints очень любят ресурсы. FK, PK, check (not null), unique — всё это ресурсы, которые тратит оракл при вышей вставке. Подумайте, если вы так гонитесь за скоростью, уверены ли вы, что вам нужно каждый раз проверять, что то что вы вставляете — соответсвует условиям constraints. Думаю ваш java код не настолько сложен и источник данных проверен и единообразен, потому можно было бы рискнуть не делать проверки при вставке (можно на крайняк сделать job, который раз в некоторое время находит «битые» данные в системе. Но констрейнты либо убрать вообще, либо оставить в декларативных целях, но воспользоваться RELY DESABLE NOVALIDATE;
4) BULK INSERT мне нравится (по сути это аналог FORALL в PL/SQL). Но если вы захотите воспользоваться вторым моим советом, то у вас возникнет вопрос, как же — частый вызов процедур из джавы в оракл — тоже ресурсоёмко и вы будете правы. Потому рекомендовал бы формировать буфер на джаве, а потом передавать в процедуру массивом сразу некоторое кол-во данных (параметр объявите как PL/SQL table). Ну и внутри PL/SQL процедуры уже bulk набор данных через уже отпарсеный запрос.
5) настройте параметры физического хранения таблицы PCTFREE/PCTUSED. PCTFREE можно поставить близким к 0. Т.к. предполагаю, что в этой таблице вам не нужны updates. Соответсвенно можно забивать датаблок «до краю». Реже выделяете новый датаблок — быстрее работаем.
6) Как у вас managed tablespace? (dictionary vs locally) Наверное уже в 2013 году вопрос не актуальный, но всё же…
7) Индексы!!! быстрый интенсивный DML и индексы — это два врага. Подумайте, так ли вам нужны индексы на этих таблицах. Тема отдельная, но если можете — лучше убейте их. Не думаю, что в контексте ваших датчиков вы будете искать строки по уникальному индексу, наверняка у вас какая-то batch обработка данных… В общем смотрите, где вы готовы потерять — при вставке почти удвоить время вставки из-за индекса или при вычитывании замедлится (ещё вопрос замедлится ли!!) из-за отсутсвия индексов!
8) Если не критично потеря небольшого кол-ва недописанных данных в случае падения инстанса (думаю вам подойдёт) почитайте про опции COMMIT NOWAIT BATCH (NOWAIT и BATCH это две раздельных фичи — почитайте).
9) По дополнительной настройке инстанса я особо не подскажу — тут DBA нужно чтобы подключились, там ещё немного можно было бы выжать (или убедится что мы не теряем на так называемой «контрольной точке» — убедитесь в достаточности размеров online redo logs итд).

Думаю если вы примените всё что я упомянул выше, вы выйдете на ещё более высокие просторы производительности в вашей системе.
Желаю удачи (если всё же попробуете применить — поделитесь результатами, пожалуйста, хотя бы в кратце — сколько в контексте ваших цифр показал прирост).

PS: Это то, что в голову пришло сразу. Может ещё чего придумаю. :)
Знаю что в Киеве кто-то организовывал на основе лего-конструктора программируемых. Где видел не помню, но может будет легче гуглить с этим знанием :)
Правда тот человек, вроде, всё-таки собирал взносы от участников секции, т.к. лего-конструкторы весьма недёшевы
Кстати, да. Тоже таким страдал
ФМ-приёмник требует понятия индуктивности… впрочем, можно не объяснять. Кстати, помню, в детстве очень удивлял одноклассников тем, что можно сделать радиоприёмник, который работает вообще без источников питания. Это всех очень впечатлсяло. Все дети понимают, что чтобы электроника / электрика работала — нужен источник энергии. Хотя бы батарейка. То что радиоволны собержат в себе энергию понять и поверить несмотря на уроки физики никто не хотел. На коробочку из конденсатора, катушки, найшника и длинной антенны смотрели как на магию.
Кстати да. Для самой примитивной светомузыки хватит 1 транзистора и диода (-ов). Проще некуда.
Ответы пошли в приват.
Если говорить обезличенно — я с этим сталкивался в двух крупных международных инвестиционных банках из top10. Занимал позиции от мид дева до Деливери менеджера. Конечно существуют workarounds, но они трудозатратные. В чистом виде доступ на unix где стоит оракл либо dba права никто не даст. Права где присутствует слово ANY — жёлтая, а то и красная карточка аудита. Это вкратце.
Увы, зачастую, даже на дев сервера доступ сильно ограничен, «чтобы_вдруг_чего_не_вышло». :-\ Таковы реалии entreprise.
Хм. Посмотрел код. Замечательно, но для моего окружения так же неприменима. Чтобы воспользоватся твоим кодом нужно как минимум:
1) GRANT CREATE ANY DIRECTORY чего в моих «энтерпрайз» окружениях я получу ни в жизни — проще получить сетевую шару на папку дампов (что тоже не просто, честно!).
2) Грант на использование джавы — отдельная тема. Вообще с джавой можно добраться на сервере много куда, куда не положено. Потому без сильной необходимости — не дадут-с.

А эта процедура уже включена в релиз, потому для сравнительно простых случаев она очень даже применима. Я не говорю про замену трейс файлов. То, для чего я их использую, всё равно не заменит ничего (ну разве что awr отчёты в некоторой мере).
PS: Кстати, вспомнил почему попробовал использовать SQL с WITH в PL/SQL.
Я в основном работаю с Oracle из PL/SQL Developer (не так old-school-но, как через sql*plus, зато удобно :) ).
И тут обнаружил, что SQL Window не поддерживает новый синтаксис — ругается.
Ок, думаю — перехожу в command window. Там та же ситуация — ругается на синтаксис.
Плюю, перехожу в честный sql*plus (но на физическом компе стоит клиент ещё от 11)… и обнаруживаю что sql*plus от 11 тоже ругается на новый синтаксис.
Чтобы не ставить новый оракл клиент или не работать из sql*plus виртуалки, думал по принципу: ОК, клиентские приложения не знают нового синтаксиса, но сервер то знает! Надо ему запилить как-то на серверную часть этот запрос. Ну а как проще всего запилить? Всунуть в PL/SQL код — пусть на сервере откомпилируется. Тут то я и узнал что PL/SQL тоже не поддерживает новый синтаксис. Причём, даже через новый SQL*Plus.
Естественно, через execute immediate он в конечном итоге был запущен, «но неприятный осадок остался».
1) Тестирую то со второго дня после релиза (с 30-го июня), но не только этим занимаюсь же — есть ещё работа. А отчего такой вывод?
2) autostart PDB — я согласен, что оракл, скорее всего считает это не багом… но это неудобно с точки зрения потребителя. Я хочу настройку/параметр стартовать ли эту базу автоматически.
3) снимать трассировку — достаточно морочное дело, скажем честно — требуется ряд дополнительных телодвижений, да и не всегда есть доступ к папке с трейсами на сервере, увы. Потому простой способ получить запрос был бы хорошим
4) «PL/SQL in SQL WITH in PL/SQL — в целом по всем пунктам комментариев согласен, однако оракл ведь декларирует, что PL/SQL вполне прозрачно поддерживает включение select / insert / update / delete выражений, но вот тут начинаются исключения. Просто не целостно выглядит. Хотя практическая польза несколько сомнительна. Но от того, что я и вы не применяем это, не значит что этого не захочет использовать ещё кто-то.
Для меня, например, использование локальных подпрограмм (например объявить процедуру внутри процедуры) есть ненужное излишество, т.к. я по большей части не использую standalone процедуры, а пишу пакеты, и я просто могу использовать приватные конструкции. При этом мне этого достаточно. Это не значит что другие не пользуются этой функциональностью в своих ситуациях или предпочтениях.
Надеюсь аналогия понятна.
Пожалуйста.
Если не сложно, можно пояснить в чём сумбурность? Мало пояснений / комментариев?
Я действительно старался не заполнять заметку «водой», а описать по возможности кратко, основываясь на субъективных предпочтениях к подаче информации. Это доставляет неудобства?
В продакшн не ставят, конечно. Потому я и написал предисловие, т.к. из версии к версии одна и та же картина.
С другой стороны, если бы не ставили совсем, и не пробовали мигрировать свои проекты, то и к следующему релизу ситуация не поменялась бы.
И, кстати, бета тест-релизы были раньше. Приблизительно год назад, если память меня не подводит. Естественно не public.

С другой стороны, большинство статей по новым фичам что я видел, полны восторгов и описуют фичи, которые, похоже, люди не попробовали дальше примера из ораклового what's new. Или решили деликатно промолчать о том, что у них не получилось и какие workarounds они применили.
Потому что, например, с тем же PDB autostart не столкнуться сложно… но ни в одной статье про multitenant я этого не видел.
С другой стороны — не факт что это баг, а не «as designed» и это поведение изменят в R2 или ещё где-то.

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

Но ваше мнения я тоже учту при размышлениях о тематике следующих статей.

С уважением.

Информация

В рейтинге
Не участвует
Откуда
Украина
Зарегистрирован
Активность