Забавно конечно. Как минимум на Ростелекоме проще найти что резольвится, чем то что не резольвится. Даже смена днс (+ flushdns) на всякие 1.1.1.1 / 8.8.8.8 не помогает.
И тем не менее, накопители SSD объёмом от 1 Тб всё ещё весьма недёшевы
HDD 1TB - 4-5к рублей, SSD 1TB - от 6.5к рублей (если не учитывать ADATA за 4.5к) на я.маркете. Неподъёмная разница в 2.5к рублей - действительно важный аргумент, особенно для нищих айтишников.
Скорее важно уточнить - это приватный ShadowSocks на своём VPS или просто какой-то публичный из интернета. Все публичные SS (и не SS) рано или поздно перебанят тупо по IP, вне зависимости от того 2022 или 2049.
Справедливо. Но я жирный текст рассматривал как визуальный якорь. Заголовок в этом случае читается целиком, по остальным пунктам глазами сначала вычленяются интересующие пункты, а детализация по мере необходимости - чтобы решить проблему перегрузки лишней информацией.
Кроме прикладного ПО есть ещё и бесчисленное количество драйверов, которые никогда не будут писать под старое железо. Поэтому, вероятно, планируется, что первые доли процентов "armdows" возможны в ноутбучном сегменте через предустановленные оем-версии, ибо ждать пока подтянутся производители нового железа и умрёт старое придётся долго. Однако даже с винбуком на арм, с потребностями, которые бы покрыл и хромобук, но когда нет гарантии что воткнутая железка не заведётся, ОС на арм будет не очень популярна.
А ну ещё забыл тоже достаточно частый вариант, с left join'ами (часто такое с представлениями (view) бывает). Тут у оракла есть возможность не только выкидывать сегмент таблицы, но даже выкидывать целые подзапросы из результирующего плана, если не нужны все поля.
DDL
create table CLIENTS as
select level as id, 'client '||level as name
from dual
connect by level <= 1000
/
ALTER TABLE CLIENTS
ADD CONSTRAINT PK_CLIENTS
PRIMARY KEY (ID)
/
create table PAYMENTS as
select c.ID * 10000 + p.PAY_ID as PAY_ID, c.ID as CLIENT_ID, 0 as PAY_SUM
from CLIENTS c, (select level as pay_id from dual connect by level <= 100) p
/
ALTER TABLE PAYMENTS
ADD CONSTRAINT PK_PAYMENTS
PRIMARY KEY (PAY_ID)
/
CREATE INDEX IDX_PAYMENTS_CLIENT_ID ON PAYMENTS
(CLIENT_ID)
/
ALTER TABLE PAYMENTS
ADD CONSTRAINT FK_PAYMENTS_CLIENT
FOREIGN KEY (CLIENT_ID)
REFERENCES CLIENTS (ID)
/
create or replace view V_PAYMENTS as
select P.*, C.NAME
from PAYMENTS P
left join CLIENTS C on P.CLIENT_ID = C.ID
/
BEGIN
SYS.DBMS_STATS.GATHER_TABLE_STATS (
OwnName => USER
,TabName => 'PAYMENTS'
,Cascade => TRUE);
SYS.DBMS_STATS.GATHER_TABLE_STATS (
OwnName => USER
,TabName => 'CLIENTS'
,Cascade => TRUE);
END;
/
Вот чисто синтетический пример с таблицами PAYMENTS и CLIENTS, завёрнутые во вьюшку так, чтобы CLIENTS соединялась через left join. Теперь посмотрим планы запросов:
Как видите во втором случае оракл полностью исключил таблицу CLIENTS из запроса. Конечно, физического смысла в такой архитектуре нет, но в жизни варианты могут быть намного сложнее и обширнее.
На самом деле есть случай, когда извлекаемые и используемые в соединении с другими таблицами целиком находятся в одном составном индексе. В этом случае оракл может вообще не обращаться к сегменту таблицы, если не требуется дополнительных полей. И тут разница уже будет - в случае со * это будет "index scan + table access", в случае выбора только проиндексированного поля - только "index scan" без обращения к таблице. Плюс ещё бывают поля с *LOB'ами которые ещё в одном сегменте находятся и могут не требоваться в данном конкретном запросе.
Без чтения планов в оракле оптимизировать что-то невозможно. Поэтому любые советы по оптимизации по хорошему нужно сопровождать демонстрацией плана запросов, например как это делал @xtender в своих статьях на orasql.org.
Что касается CTE в оракле, то использовать их нужно с умом - они могут материализовываться в отдельную временную таблицу, а могут и инлайниться, встраиваюсь в запрос таким образом, как будто CTE и нет вообще, форсированно этим можно управлять соответствующими хинтами MATERIALIZE и INLINE соответственно. CTE c материализацией часто используется для следующей цели - допустим у нас есть тяжелый подзапрос с большим количеством соединений, возвращающий очень малое количество строк. И этот подзапрос нужно связать с другим сложным подзапросом или представлением - чтобы оракл не пытался объединить эти две части, ломая хорошо оптимизированные подзапросы, которые вернут условно по три строчки за пол секунды каждый, в один мегазапрос с кучей рейндж или фулл сканов, который будет работать пол часа. Поэтому надо чётко понимать, что заинлайненный СТЕ - это просто декорация, а материализованный - временная таблица, в которую выгружены все данные из подзапроса СТЕ. В вашем случае без CTE вероятно как раз и родился такой мегазапрос, который отъедал temp на группировках/сортировках, а переписав его на CTE вы материализовали какую-то его часть в отдельный подзапрос, который выполнился отдельно и выгрузился во временную таблицу и дальше уже использовались только результирующие строки из него.
Ещё в школе наткнулся на отличную русскоязычную справку в Турбо Паскале с гиперссылками и примерами, что сразу сподвигло изучать язык и программирование в частности даже за пределами преподаваемого на уроках. Думаю если бы не это, то я бы и не стал программистом.
На оракле можно было бы решить через model, например -
Запрос
with journal as
(
select 1 as id, '127.0.0.1' as ip, to_timestamp('01.01.2010 10:10','dd.mm.yyyy HH24:mi') as time from dual union all
select 2 as id, '8.8.8.8' as ip, to_timestamp('02.01.2010 11:15','dd.mm.yyyy HH24:mi') as time from dual union all
select 3 as id, '127.0.0.1' as ip, to_timestamp('03.01.2010 12:20','dd.mm.yyyy HH24:mi') as time from dual union all
select 4 as id, '127.0.0.1' as ip, to_timestamp('04.01.2010 13:25','dd.mm.yyyy HH24:mi') as time from dual union all
select 5 as id, '8.8.8.8' as ip, to_timestamp('05.01.2010 14:30','dd.mm.yyyy HH24:mi') as time from dual union all
select 6 as id, '127.0.0.1' as ip, to_timestamp('06.01.2010 15:35','dd.mm.yyyy HH24:mi') as time from dual union all
select 7 as id, '8.8.8.8' as ip, to_timestamp('07.01.2010 16:40','dd.mm.yyyy HH24:mi') as time from dual union all
select 8 as id, '127.0.0.1' as ip, to_timestamp('08.01.2010 17:45','dd.mm.yyyy HH24:mi') as time from dual union all
select 9 as id, '127.0.0.1' as ip, to_timestamp('09.01.2010 18:50','dd.mm.yyyy HH24:mi') as time from dual union all
select 10 as id, '1.1.1.1' as ip, to_timestamp('10.01.2010 19:55','dd.mm.yyyy HH24:mi') as time from dual union all
select 11 as id, '1.1.1.1' as ip, to_timestamp('11.01.2010 20:55','dd.mm.yyyy HH24:mi') as time from dual
)
select ip, third_visit
from journal j
model
return updated rows -- будем брать только те строки, что попали под правила
partition by (j.ip)
dimension by (
-- нам понадобится номер посещения по IP
row_number() over (partition by j.ip order by j.time, j.id) as num_visit,
-- и всего посещений
count(*) over (partition by j.ip) as total_visits
)
measures (cast(null as timestamp) as third_visit, j.time)
rules
(
-- возьмём дату третьего посещения, если всего посещений >= 3
third_visit[num_visit = 3, total_visits >= 3] = time[cv(), cv()],
-- возьмем пустую дату для первой строки по IP, если всего посешений меньше 3
third_visit[num_visit = 1, total_visits < 3] = null
)
/
Я считал, что нужно найти третье посещение, а не третье посещение за день. Но это что-то нифига не базовый уровень :D Базовый уровень - это подзапрос с аналитикой.
Предлагаю сначала на чем-нибудь простеньком потренироваться, типа Сахары или Гоби. Когда обкатаем превращение пустынь в цветущие оазисы до совершенства, там уже можно планку выше поднимать.
Забавно конечно. Как минимум на Ростелекоме проще найти что резольвится, чем то что не резольвится. Даже смена днс (+ flushdns) на всякие 1.1.1.1 / 8.8.8.8 не помогает.
google.ru
dns.yandex.ru
HDD 1TB - 4-5к рублей, SSD 1TB - от 6.5к рублей (если не учитывать ADATA за 4.5к) на я.маркете. Неподъёмная разница в 2.5к рублей - действительно важный аргумент, особенно для нищих айтишников.
Вот и дожили до времён, когда даже notepad не стартует мгновенно.
Ждём теперь блокировку гитхаба?
Firefox, Vivaldi, Opera, Я.Браузер, Brave и сам Edge есть в Microsoft Store.
Скорее важно уточнить - это приватный ShadowSocks на своём VPS или просто какой-то публичный из интернета. Все публичные SS (и не SS) рано или поздно перебанят тупо по IP, вне зависимости от того 2022 или 2049.
Справедливо. Но я жирный текст рассматривал как визуальный якорь. Заголовок в этом случае читается целиком, по остальным пунктам глазами сначала вычленяются интересующие пункты, а детализация по мере необходимости - чтобы решить проблему перегрузки лишней информацией.
А если структурировать?
Горячей воды не будет!
Период: с 10 по 15 июня
Причина: ежегодный профилактический ремонт теплосетей
По вопросам обращаться: ооо ук1, тел. 123-123-123
Кроме прикладного ПО есть ещё и бесчисленное количество драйверов, которые никогда не будут писать под старое железо. Поэтому, вероятно, планируется, что первые доли процентов "armdows" возможны в ноутбучном сегменте через предустановленные оем-версии, ибо ждать пока подтянутся производители нового железа и умрёт старое придётся долго. Однако даже с винбуком на арм, с потребностями, которые бы покрыл и хромобук, но когда нет гарантии что воткнутая железка не заведётся, ОС на арм будет не очень популярна.
BLOB — булевая переменная
Булевая - это true/false. Блобы - это массивы двоичных данных обычно.
А ну ещё забыл тоже достаточно частый вариант, с left join'ами (часто такое с представлениями (view) бывает). Тут у оракла есть возможность не только выкидывать сегмент таблицы, но даже выкидывать целые подзапросы из результирующего плана, если не нужны все поля.
DDL
Вот чисто синтетический пример с таблицами PAYMENTS и CLIENTS, завёрнутые во вьюшку так, чтобы CLIENTS соединялась через left join. Теперь посмотрим планы запросов:
Со *:
С конкретными полями:
Как видите во втором случае оракл полностью исключил таблицу CLIENTS из запроса. Конечно, физического смысла в такой архитектуре нет, но в жизни варианты могут быть намного сложнее и обширнее.
На самом деле есть случай, когда извлекаемые и используемые в соединении с другими таблицами целиком находятся в одном составном индексе. В этом случае оракл может вообще не обращаться к сегменту таблицы, если не требуется дополнительных полей. И тут разница уже будет - в случае со * это будет "index scan + table access", в случае выбора только проиндексированного поля - только "index scan" без обращения к таблице. Плюс ещё бывают поля с *LOB'ами которые ещё в одном сегменте находятся и могут не требоваться в данном конкретном запросе.
Запрос со *:
Запрос с полем:
Без чтения планов в оракле оптимизировать что-то невозможно. Поэтому любые советы по оптимизации по хорошему нужно сопровождать демонстрацией плана запросов, например как это делал @xtender в своих статьях на orasql.org.
Что касается CTE в оракле, то использовать их нужно с умом - они могут материализовываться в отдельную временную таблицу, а могут и инлайниться, встраиваюсь в запрос таким образом, как будто CTE и нет вообще, форсированно этим можно управлять соответствующими хинтами MATERIALIZE и INLINE соответственно. CTE c материализацией часто используется для следующей цели - допустим у нас есть тяжелый подзапрос с большим количеством соединений, возвращающий очень малое количество строк. И этот подзапрос нужно связать с другим сложным подзапросом или представлением - чтобы оракл не пытался объединить эти две части, ломая хорошо оптимизированные подзапросы, которые вернут условно по три строчки за пол секунды каждый, в один мегазапрос с кучей рейндж или фулл сканов, который будет работать пол часа. Поэтому надо чётко понимать, что заинлайненный СТЕ - это просто декорация, а материализованный - временная таблица, в которую выгружены все данные из подзапроса СТЕ. В вашем случае без CTE вероятно как раз и родился такой мегазапрос, который отъедал temp на группировках/сортировках, а переписав его на CTE вы материализовали какую-то его часть в отдельный подзапрос, который выполнился отдельно и выгрузился во временную таблицу и дальше уже использовались только результирующие строки из него.
Думается мне красивых имён аккаунтов хватит ещё на десяток подобных новостей.
Ещё в школе наткнулся на отличную русскоязычную справку в Турбо Паскале с гиперссылками и примерами, что сразу сподвигло изучать язык и программирование в частности даже за пределами преподаваемого на уроках. Думаю если бы не это, то я бы и не стал программистом.
Это уже из статьи видно, не "смешной милый котик дарит цветок", а кот с цветком по факту.
А CTE разве не будет считаться подзапросом? А ещё у вас выпали IP адреса, у которых было меньше 3-х посещений.
На оракле можно было бы решить через model, например -
Запрос
Вывод:
Я считал, что нужно найти третье посещение, а не третье посещение за день. Но это что-то нифига не базовый уровень :D Базовый уровень - это подзапрос с аналитикой.
И в оракле тоже оптимизатор, а планировщиком Oracle Scheduler называют, который джобиками оркестрирует.
Предлагаю сначала на чем-нибудь простеньком потренироваться, типа Сахары или Гоби. Когда обкатаем превращение пустынь в цветущие оазисы до совершенства, там уже можно планку выше поднимать.