Обновить
79
Sayan Malakshinov@xtender

FBCS, Oracle ACE, performance tuning expert

93
Подписчики
Отправить сообщение

Расскажите чуть подробнее, пожалуйста, что будет в выступлении про интеграционные тесты с Oracle, чтобы знать будет это мне интересно как ораклисту или нет?

Да и вообще, 300мс — я бы категорически не назвал высокой скоростью, а уж для простенького джойника по 50к «быстро» вообще должно быть где-то в диапазоне 5-15мс…
Режим «только для чтения»
В Oracle, SQL Server и некоторых других базах он вообще не работает :)
Вот, что делает наш read-only
В оракле можете просто добавить вызов set transaction read only;

В Oracle с этим все легко и просто:
1. Можно использовать композитное секционирование, например: интервальное секционирование по датам datetime и подсекции по message. Допустим, каждая секция содержит только одни сутки, и каждая подсекция только свой message. В таком случае индексы вообще будут не нужны, поэтому такой вариант обычно и рекомендуется для логов, т.к. там нагрузка в основном write-only.
2. если лидирующее поле/поля в индексе имеет небольшое количество разных значений и в запросе нет по нему предиката, но есть хороший селективный предикат по второму полю из индекса, то может использоваться Index Skip Scan
Хмъ, я не понял что именно вы в 9-й задаче считаете? Количество комбинаций чего?
Ваше решение работает на моем наборе аж 40 сек.
create table a(n) as 
select ceil(dbms_random.value(0,500)) n from dual connect by level<=1e4;

А на наборе от 0 до 9 оно возвращает аж 670 — что это такое, если даже количество сумм равно 249?
with a(n) as (select level-1 from dual connect by level<=10)
select sum(x*x)
  from (select count(*) x
        from a t1
           , a t2
        group by t1.n + t2.n)

И покажите, пожалуйста, ваше решение для 8-й задачи
Молодцы, хорошая затея! :)
В 7-й задаче, я бы лучше предложил решать через PL/SCOPE, как мне кажется это было бы правильнее, чем самому парсить. Нужно было лишь откомпилить объекты с alter session set PLSCOPE_SETTINGS='IDENTIFIERS:ALL' и смотреть где CALL к нужной процедуре и REFERENCE к нужному пакету совпадают dba_identifiers.usage

Еще мне кажется, что после 8-й задачи 9-я становится лишней и не является оптимальной, т.к. оптимальным должно быть сокращение объемов только до сумм и произведений, например так:
with 
-- закомментировал тестовый генератор
 --a(n) as (select/*+ cardinality(1000) */ level-1 n from dual connect by level<=1000),
 ----------------------
 -- calc: пошли вычисления
 -- аггрегируем уникальные числа, чтобы уменьшить объемы для перебора
 x0 as (select n,count(*) cnt from a group by n order by n)
 -- за один "урезанный" селф-джойн рассчитываем и суммируем сразу и суммы и произведения:
,x1 as (
  select
     x.n + y.n as s
    ,x.n * y.n as m
   ,2*sum(x.cnt*y.cnt) cnt
  from x0 x,x0 y
  where y.n>=x.n -- возьмем только один вариант и просто умножим на 2
  group by
     x.n + y.n
    ,x.n * y.n
)
-- тут уже объем для перебора становится практически минимальным:
select sum(x1.cnt*x2.cnt) total
from x1,x1 x2
where x1.s=x2.m;

C таким вариантом, у меня на такой тестовой табличке:
create table a(n) as select ceil(dbms_random.value(0,500)) n from dual connect by level<=1e4ж
решается за 0.5сек. Если же начать собирать сами комбинации чисел, то объемы и время расчета существенно вырастут. По идее, есть еще эвристики для уменьшения перебора да и оптимизации, например, автоматическое деление на группы диапазонов, но их делать уже будет сложнее и в условиях спешки я бы не стал их заморачиваться
А, понятно, старый добрый start-of-group :) кстати, конкретно этот пример и легче, и быстрее, и понятнее решается с помощью pattern matching:
pattern matching
WITH ALL_DATA AS (
  SELECT TO_DATE('01.01.2018 00:00:28', 'DD.MM.YYYY HH24:MI:SS') SDATE, 5 SPEED, 0.01 DISTANCE FROM DUAL
  UNION ALL SELECT TO_DATE('01.01.2018 00:01:28', 'DD.MM.YYYY HH24:MI:SS') SDATE, 25 SPEED, 0.1 DISTANCE FROM DUAL
  UNION ALL SELECT TO_DATE('01.01.2018 00:02:31', 'DD.MM.YYYY HH24:MI:SS') SDATE, 61 SPEED, 0.3 DISTANCE FROM DUAL
  UNION ALL SELECT TO_DATE('01.01.2018 00:02:58', 'DD.MM.YYYY HH24:MI:SS') SDATE, 68 SPEED, 0.3 DISTANCE FROM DUAL
  UNION ALL SELECT TO_DATE('01.01.2018 00:05:01', 'DD.MM.YYYY HH24:MI:SS') SDATE, 45 SPEED, 0.1 DISTANCE FROM DUAL
  UNION ALL SELECT TO_DATE('01.01.2018 00:06:28', 'DD.MM.YYYY HH24:MI:SS') SDATE, 25 SPEED, 0.1 DISTANCE FROM DUAL
  UNION ALL SELECT TO_DATE('01.01.2018 00:07:28', 'DD.MM.YYYY HH24:MI:SS') SDATE, 25 SPEED, 0.1 DISTANCE FROM DUAL
  UNION ALL SELECT TO_DATE('01.01.2018 00:08:28', 'DD.MM.YYYY HH24:MI:SS') SDATE, 70 SPEED, 0.9 DISTANCE FROM DUAL
  UNION ALL SELECT TO_DATE('01.01.2018 00:09:28', 'DD.MM.YYYY HH24:MI:SS') SDATE, 75 SPEED, 0.9 DISTANCE FROM DUAL
  UNION ALL SELECT TO_DATE('01.01.2018 00:10:28', 'DD.MM.YYYY HH24:MI:SS') SDATE, 78 SPEED, 0.9 DISTANCE FROM DUAL
  UNION ALL SELECT TO_DATE('01.01.2018 00:11:28', 'DD.MM.YYYY HH24:MI:SS') SDATE, 50 SPEED, 0.1 DISTANCE FROM DUAL
)
, T AS (
  SELECT SDATE, SPEED, DISTANCE
  , GROUP_NUMBER(CASE WHEN D.SPEED > 60 THEN 1 ELSE 0 END) OVER (ORDER BY D.SDATE) ГР
  ,dense_rank()over(ORDER BY D.SDATE, CASE WHEN D.SPEED > 60 THEN 1 ELSE 0 END) ГР2
  ,CASE WHEN SPEED > 60 THEN 1 ELSE 0 END as FLAG
  FROM ALL_DATA D
)
select
  *
from t
MATCH_RECOGNIZE (
  ORDER by SDATE
  MEASURES
     speeding.SDATE as speeding_start,
     last(sdate)    as speeding_end,
     count(*)       as points,
     sum(distance)  as distance,
     (last(sdate)-first(sdate))*24*60 as TIME_MIN,
     sum(distance)/nullif((last(sdate)-first(sdate))*24,0) as AVG_SPEED
  PATTERN (speeding+)
  DEFINE speeding as (speeding.SPEED>60)
)

А что именно вы хотите-то? Ваш пример недетерминирован. А из словесного описания функции как раз напрашивается dense_rank.

И это правильно, иначе попробуйте представить себе что должен был бы тогда возвращать SUM()OVER() в следующем запросе:
with o(c, n) as (
  select 'A', 1 from dual union all
  select 'A', 2 from dual union all
  select 'A', 3 from dual union all
  select 'B', 1 from dual union all
  select 'C', 1 from dual union all
  select 'C', 2 from dual union all
  select 'C', 2 from dual union all
  select 'C', 3 from dual union all
  select 'C', 4 from dual
)
SELECT c,n
      ,sum(n)over(order by c) n_summ
FROM O;

Если бы мы хотели добавить агрегировать и при изменении N то должны были бы и показать/определить порядок сортировки при этой агрегации, например:
sum(n)over(order by c, n desc) n_summ
Это ожидаемый результат, из доки:
Invoked by Oracle as the last step of aggregate computation.

У такого окна изменение LAST_DDL_TIME и есть последний шаг агрегации. Функция-то все-таки агрегатная, если бы она возвращала каждый раз разные значения, это уже не агрегатной функцией было бы.
Кстати, а чем не подошел dense_rank?
dense_rank()OVER (ORDER BY O.LAST_DDL_TIME,O.OBJECT_TYPE) grp
Профакапил апгрейд СУБД до новой версии — и живи как хочешь. Без данных, без всего.
Это как так надо постараться, чтобы данные потерять при апгрейде? Это ж надо еще умудриться не сделать ни холодного, ни горячего бэкапа, не иметь стендбая, да еще и поменять compatibity…
взяли последнюю актуальную с надеждой что содержит в себе последние обновления.
не забывайте, что помимо исправлений, она содержит в себе и очень много нововведений, из-за которых очень повышается риск на новые доселе невиданные баги.
не прощающая ошибок
наоборот, с ним надо очень хорошо постараться, чтобы профакапить данные. Он как раз оооочень многое прощает как админам, так и разработчикам :)
надо открывать саппорт реквест, а не на sql.ru отераться.
одно другому не мешает, поэтому желательно сделать и то, и другое, т.к. с техподдержкой есть шанс прождать пару месяцев в ожидании патча даже для critical SR или не решить свою проблему вообще, а спецы на форуме есть с уровнем гораздо выше средней у техподдержки
И нафига там размещать процедуры и функции?!
Ни разу не встречал когда нужны функции и сам придумать не можешь?
Я не могу использовать уже определенные представления в других представлениях.
Не понял? Почему не можешь?
SQL> with
  2   a(a) as (select 1 from dual)
  3  ,b(b) as (select * from a)
  4  ,c(c) as (select * from b)
  5  select *
  6* from a,b,c;

         A          B          C
---------- ---------- ----------
         1          1          1


Есть, то он есть, но вот работать с ним нельзя, т.к. убожество полное.
Забавно слышать, т.к. в PG возможностей еще меньше…
У автора просто пример надуманный… Конечно, практически всегда лучше следовать мантре от Тома Кайта:
I have a pretty simple mantra when it comes to developing database software, and I have written this many times over the years:
  • You should do it in a single SQL statement if at all possible.
  • If you cannot do it in a single SQL statement, do it in PL/SQL.
  • If you cannot do it in PL/SQL, try a Java stored procedure.
  • If you cannot do it in Java, do it in a C external procedure.
  • If you cannot do it in a C external procedure, you might want to seriously think about why it is you need to do it.


Но иногда, в крайне редких случаях, по производительности лучше использовать PL/SQL, я писал пару примеров тут: orasql.org/2014/02/28/straight-sql-vs-sql-and-plsql

И кстати, насчет обычных табличных неконвеерных функций: чуть менее месяца назад, я как раз разбирался с тем, что неконвеерные функции ужасно медленно возвращают результаты в SQL, причем настолько, что даже если у вас уже есть такая функция, то будет быстрее, если просто напишите конвеерную функцию-обертку, в которой будете получать весь результат неконвеерной и возвращать через пайплайн: orasql.org/2017/12/13/collection-iterator-pickler-fetch-pipelined-vs-simple-table-functions
«WITH» есть в Oracle, причем он функционально гораздо шире, чем в PostgreSQL. Там сейчас можно даже процедуры и функции размещать.

ЗЫ. Не истины ради, а холивара для в Oracle исторически многое очень хорошо оптимизировано, включая PL/SQL, причем настолько много, что мало кто знает о таких оптимизациях и как они работают, что потом удивляются почему «то же самое» на других СУБД выполняется очень медленно.
У меня пару вопросов сразу возникло:
1. Почему сразу не создали SR c severity 1 + 24*7, а еще лучше сразу звонком в российскую тех.поддержку?
2. Почему не обратились ни на sql.ru, ни в телеграмм канал RuOUG? Там полно высококлассных спецов, которые зачастую помогают решить сложнейшие проблемы и намного быстрее, чем техподдержка
3. Почему выбрали 12.2, а не гораздо более стабильную 12.1.0.2?
4. Как же вы так тестировали, что упустили даже проблему с версией клиента, да и быстрее было бы просто установить SQLNET.ALLOWED_LOGON_VERSION_CLIENT. Кстати, может вы ошиблись с версией ораклового клиента, т.к. дефолтно на 12.2 стоит 11:
docs.oracle.com/en/database/oracle/oracle-database/12.2/netrf/parameters-for-the-sqlnet-ora-file.html#GUID-B2908ADF-0973-44A9-9B34-587A3D605BED
Полностью согласен! Когда я был «молод и горяч», в порывах энтузиазма очень сильно перерабатывал. Так и от поведение «Рика» веет молодостью. В последние же лет 5-6 я очень ценю свое время, поэтому предпочитаю обучить и разъяснить коллегам всё как можно более детально, т.к. мне же самому от этого становится намного легче и интереснее работать: снижаем кол-во вопросов по пустякам, разделяем простую работу на большее кол-во сотрудников. Да даже элементарно интереснее общаться с коллегами, когда делишься опытом и они близки к тебе по уровню знаний

Информация

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