Основы языка Питон: функции, элементы функционального программирования, списочные выражения, генераторы. Презентация к лекции курса "Технологии и языки программирования".
Основы языка Питон: функции, элементы функционального программирования, списочные выражения, генераторы. Презентация к лекции курса "Технологии и языки программирования".
Sphinx считается одним из самых быстрых и гибких поисковых движков на рынке, но не является "коробочным" решением, чем отпугивает многих разработчиков. Я расскажу как быстро поднять полнотекстовый поиск для своего проекта на базе Sphinx, почему он крут и какие существуют интеграционные решения для Python.
Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"Fwdays
Let's calculate an average of one column for each key, like the following query: SELECT key, avg(value) FROM table GROUP BY key. What can be more simple? But the question is: what is the most efficient way to do it? How to write code to achieve maximum performance on a variety of hardware?
Современному хайлоду - современные решения: MySQL 8.0 и улучшения PerconaSveta Smirnova
MySQL всегда использовали под высокой нагрузкой. Недаром эта база была и остаётся самым популярным бэкэндом для web. Однако наши представления о хайлоде с каждым годом расширяются. Большая скорость передачи данных -> больше устройств с подключением к интернет -> больше пользователей -> больше данных.
Задачи, стоящие перед разработчиками MySQL, с каждым годом усложняются.
В этом докладе я расскажу как менялись сценарии использования MySQL за [почти] 25 лет её истории и что делали инженеры, чтобы MySQL оставалась актуальной. Мы затронем такие темы, как работа с большим количеством активных соединений и высокими объёмами данных. Я покажу насколько современные версии лучше справляются с возросшими нагрузками.
Я надеюсь, что после моего доклада те слушатели, которые используют старые версии, захотят обновиться и те, кто уже обновились, узнают как использовать современный MySQL на полную мощность.
Прочитана на конференции OST 2020: https://ostconf.com/materials/2857#2857
#RuPostgresLive 4: как писать и читать сложные SQL-запросыNikolay Samokhvalov
Онлайн-опросы неизменно показывают — всех нас очень интересуют две вещи: а) как писать наиболее эффективные SQL-запросы, б) как «читать» такие запросы, а точнее, как понимать, что именно делает или будет делать СУБД при их выполнении.
Эти две неразрывно связанные друг с другом темы чрезвычайно обширны, SQL-искусству можно (и нужно) учиться годами. Во время нашей очередной встречи в прямом эфире мы затронем некоторые аспекты обеих.
ЧАСТЬ 1: EXPLAIN
Алексей Ермаков. Как читать и интерпретировать вывод команды EXPLAIN
Команда EXPLAIN — основной инструмент анализа запросов, позволяющий разобраться, каким образом запрос будет выполняться и как можно его ускорить. Для сложных запросов вывод может быть довольно громоздким и его становится сложно читать. Я расскажу, из каких частей состоит план запроса, на какие «маркеры» в нём следует обращать внимание в первую очередь и как на это реагировать.
ЧАСТЬ 2: ADVANCED SQL
Николай Самохвалов. SQL современный и «продвинутый»
«Я не волшебник, я только учусь». Продвинутому SQL нас постоянно учат такие видные гуру как Markus Winand и Макс Богук. Рекурсивные CTE, LATERAL JOIN, виртуозная работа с массивами и строками, window functions и прочие модные штучки, которые помогут вам в дрессировке вашего Постгреса, — я постараюсь сделать хороший обзор, а если вдруг тема покажется интересной, то в следующих сеансах группового Постгреса мы обязательно пригласим настоящих гуру :)
PG Day'14 Russia, PostgreSQL как платформа для разработки приложений, часть 3...pgdayrussia
Доклад был представлен на официальной российской конференции PG Day'14 Russia, посвященной вопросам разработки и эксплуатации PostgreSQL.
Уникальный семинар от опытного "базиста" Ивана Фролкова призван наглядно пояснить слушателям адекватность применения реляционных СУБД на задачах веба. В рамках доклада Иван рассмотрит типичные "грабли", на которые натыкаются разработчики, и субоптимальные решения, изобретаемые с целью побороть возникшие проблемы. В качестве альтернативы, коллега Фролков наглядно пояснит, как эти же задачи решаются штатными средствами PostgreSQL.
В качестве бонуса Иван — "ветеран" промышленной разработки ПО для реляционных СУБД — проведет краткий ликбез по рекомендуемым практикам построения SQL-запросов и программирования на языке PL/PGSQL.
Sphinx считается одним из самых быстрых и гибких поисковых движков на рынке, но не является "коробочным" решением, чем отпугивает многих разработчиков. Я расскажу как быстро поднять полнотекстовый поиск для своего проекта на базе Sphinx, почему он крут и какие существуют интеграционные решения для Python.
Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"Fwdays
Let's calculate an average of one column for each key, like the following query: SELECT key, avg(value) FROM table GROUP BY key. What can be more simple? But the question is: what is the most efficient way to do it? How to write code to achieve maximum performance on a variety of hardware?
Современному хайлоду - современные решения: MySQL 8.0 и улучшения PerconaSveta Smirnova
MySQL всегда использовали под высокой нагрузкой. Недаром эта база была и остаётся самым популярным бэкэндом для web. Однако наши представления о хайлоде с каждым годом расширяются. Большая скорость передачи данных -> больше устройств с подключением к интернет -> больше пользователей -> больше данных.
Задачи, стоящие перед разработчиками MySQL, с каждым годом усложняются.
В этом докладе я расскажу как менялись сценарии использования MySQL за [почти] 25 лет её истории и что делали инженеры, чтобы MySQL оставалась актуальной. Мы затронем такие темы, как работа с большим количеством активных соединений и высокими объёмами данных. Я покажу насколько современные версии лучше справляются с возросшими нагрузками.
Я надеюсь, что после моего доклада те слушатели, которые используют старые версии, захотят обновиться и те, кто уже обновились, узнают как использовать современный MySQL на полную мощность.
Прочитана на конференции OST 2020: https://ostconf.com/materials/2857#2857
#RuPostgresLive 4: как писать и читать сложные SQL-запросыNikolay Samokhvalov
Онлайн-опросы неизменно показывают — всех нас очень интересуют две вещи: а) как писать наиболее эффективные SQL-запросы, б) как «читать» такие запросы, а точнее, как понимать, что именно делает или будет делать СУБД при их выполнении.
Эти две неразрывно связанные друг с другом темы чрезвычайно обширны, SQL-искусству можно (и нужно) учиться годами. Во время нашей очередной встречи в прямом эфире мы затронем некоторые аспекты обеих.
ЧАСТЬ 1: EXPLAIN
Алексей Ермаков. Как читать и интерпретировать вывод команды EXPLAIN
Команда EXPLAIN — основной инструмент анализа запросов, позволяющий разобраться, каким образом запрос будет выполняться и как можно его ускорить. Для сложных запросов вывод может быть довольно громоздким и его становится сложно читать. Я расскажу, из каких частей состоит план запроса, на какие «маркеры» в нём следует обращать внимание в первую очередь и как на это реагировать.
ЧАСТЬ 2: ADVANCED SQL
Николай Самохвалов. SQL современный и «продвинутый»
«Я не волшебник, я только учусь». Продвинутому SQL нас постоянно учат такие видные гуру как Markus Winand и Макс Богук. Рекурсивные CTE, LATERAL JOIN, виртуозная работа с массивами и строками, window functions и прочие модные штучки, которые помогут вам в дрессировке вашего Постгреса, — я постараюсь сделать хороший обзор, а если вдруг тема покажется интересной, то в следующих сеансах группового Постгреса мы обязательно пригласим настоящих гуру :)
PG Day'14 Russia, PostgreSQL как платформа для разработки приложений, часть 3...pgdayrussia
Доклад был представлен на официальной российской конференции PG Day'14 Russia, посвященной вопросам разработки и эксплуатации PostgreSQL.
Уникальный семинар от опытного "базиста" Ивана Фролкова призван наглядно пояснить слушателям адекватность применения реляционных СУБД на задачах веба. В рамках доклада Иван рассмотрит типичные "грабли", на которые натыкаются разработчики, и субоптимальные решения, изобретаемые с целью побороть возникшие проблемы. В качестве альтернативы, коллега Фролков наглядно пояснит, как эти же задачи решаются штатными средствами PostgreSQL.
В качестве бонуса Иван — "ветеран" промышленной разработки ПО для реляционных СУБД — проведет краткий ликбез по рекомендуемым практикам построения SQL-запросов и программирования на языке PL/PGSQL.
2. dataegret.com
Data Egret (в прошло PostgreSQL-Consulting.com) вот уже много
лет занимается поддержкой PostgreSQL в России и за рубежом.
Лично я работаю с PostgreSQL больше 18 лет (еще с версии 7.3).
27/7 поддержка
консультации по работе базой и ее настройкам
Аудит состояния и настроек базы
Мониторинг
Обучение
О DataEgret
4. dataegret.com
Некоторые типы запросов PostgreSQL не умеет выполнять
эффективно (пока что?)
Альтернативный подход.
Ручная реализация быстрого алгоритма может дать
большое ускорение запросов
Это выглядит как магия в начале.
5. dataegret.com
Знание как работают следующие фичи базы:
WITH [RECURSIVE]
[JOIN] LATERAL
UNNEST [WITH ORDINALITY]
И так далее
Навыки требуемые для понимания материала
6. dataegret.com
PostgreSQL 9.6
Будет работать на 9.5 и 9.4 без (серьезных) правок
Миграция на 9.3 (и даже на 8.4) возможна, но надо
будет реализовывать руками отсуствующие в этих
версиях возможности.
Версия PostgreSQL
7. dataegret.com
Описание проблемы
Подготовка данных
Стандартная реализация на SQL
EXPLAIN (ANALYZE, TIMING false, COSTS false)
Альтернативное решение
EXPLAIN (ANALYZE, TIMING false, COSTS false)
У нея внутри неонка! (или смотрим под капот)
Структура
9. dataegret.com
Описание проблемы01
Queries with large ofset are slow
To produce 1.000.001’st row, database frst going to iterate through
1.000.000 rows
Alternatve: use fast Index Only Scan to skip the frst 1.000.000 rows
10. dataegret.com
Подготовка данных01
CREATE TABLE t AS select
id,
'some very boring payload text ...'::text AS payload
FROM generate_series(1, 1000000) AS g(id);
ALTER TABLE t ADD PRIMARY KEY(id);
VACUUM ANALYZE t;
13. dataegret.com
Альтернативное решение01
WITH _start AS (
--find a starting id using IOS to skip OFFSET rows
SELECT id FROM t
ORDER BY id OFFSET 999999 LIMIT 1
)
--return result using normal index scan
SELECT * FROM t WHERE id>(SELECT id FROM _start)
ORDER BY id LIMIT 5;
14. dataegret.com
EXPLAIN ANALYZE01
Limit (actual rows=5 loops=1)
CTE _start
-> Limit (actual rows=1 loops=1)
-> Index Only Scan using t_pkey on t t_1
(actual rows=1000000 loops=1)
InitPlan 2 (returns $1)
-> CTE Scan on _start (actual rows=1 loops=1)
-> Index Scan using t_pkey on t (actual rows=5 loops=1)
Index Cond: (id > $1)
Execution time: 80 ms
15. dataegret.com
Под капотом01
SELECT * FROM t WHERE id>999998 ORDER BY id LIMIT 9;
id | payload
---------+---------
999999 | payload
1000000 | payload
1000001 | payload
1000002 | payload
1000003 | payload
1000004 | payload
1000005 | payload
1000006 | payload
16. dataegret.com
Под капотом01
SELECT * FROM t ORDER BY id OFFSET 1000000 LIMIT 5;
пропускаем 1000000 строк из TABLE
id | payload
---------+---------
...
999999 | payload
1000000 | payload
1000001 | payload
1000002 | payload
1000003 | payload
1000004 | payload
1000005 | payload
1000006 | payload
17. dataegret.com
Под капотом01
_start AS (SELECT id FROM t ORDER BY id OFFSET 999999 LIMIT 1)
= 1000000, пропускаем 999999 строк из INDEX ONLY
id | payload
---------+---------
...
999999 | payload
1000000 | payload
1000001 | payload
1000002 | payload
1000003 | payload
1000004 | payload
1000005 | payload
1000006 | payload
18. dataegret.com
Под капотом01
SELECT * FROM t WHERE id>(SELECT id FROM _start)
ORDER BY id LIMIT 5; --читаем 5 строк из TABLE
id | payload
---------+---------
999999 | payload
1000000 | payload
1000001 | payload
1000002 | payload
1000003 | payload
1000004 | payload
1000005 | payload
1000006 | payload
21. dataegret.com
Подготовка данных02
CREATE TABLE t AS SELECT
id,
(Random()*100000)::integer AS f1,
(Random()*100000)::integer AS f2,
'some very boring payload text ...'::text AS payload
FROM generate_series(1, 1000000) AS g(id);
CREATE INDEX t_f1_key ON t(f1);
VACUUM ANALYZE t;
24. dataegret.com
Альтернативное решение02
WITH _t1 AS (
--lastN order by f1
SELECT * FROM t ORDER BY f1 LIMIT 5
), _max AS (
--max f1 value from lastN
SELECT max(f1) AS f1 FROM _t1
), _t2 AS (
--all lastN with f1 < max
SELECT * FROM _t1 WHERE f1<(SELECT _max.f1 FROM _max)
)
SELECT * FROM _t2
UNION ALL (
--grab required amount of additional values from table
SELECT * FROM t WHERE f1=(SELECT _max.f1 FROM _max)
ORDER BY f1, f2 LIMIT (5 - (SELECT COUNT(*) FROM _t2))
) ORDER BY f1,f2;
25. dataegret.com
EXPLAIN ANALYZE02
Sort (actual rows=5 loops=1)
Sort Key: _t2.f1, _t2.f2
Sort Method: quicksort Memory: 45kB
CTE _t1
-> Limit (actual rows=10 loops=1)
-> Index Scan using t_f1_key on t t_1 (actual rows=5 loops=1)
CTE _max
-> Aggregate (actual rows=1 loops=1)
-> CTE Scan on _t1 (actual rows=5 loops=1)
CTE _t2
-> CTE Scan on _t1 _t1_1 (actual rows=2 loops=1)
Filter: (f1 < $2)
Rows Removed by Filter: 3
InitPlan 3 (returns $2)
-> CTE Scan on _max (actual rows=1 loops=1)
-> Append (actual rows=5 loops=1)
-> CTE Scan on _t2 (actual rows=2 loops=1)
-> Limit (actual rows=3 loops=1)
InitPlan 5 (returns $4)
-> CTE Scan on _max _max_1 (actual rows=1 loops=1)
InitPlan 6 (returns $5)
-> Aggregate (actual rows=1 loops=1)
-> CTE Scan on _t2 _t2_1 (actual rows=3 loops=1)
-> Sort (actual rows=3 loops=1)
Sort Key: t.f2
Sort Method: top-N heapsort Memory: 31kB
-> Index Scan using t_f1_key on t (actual rows=3 loops=1)
Index Cond: (f1 = $4)
Execution time: 0.133 ms
26. dataegret.com
Под капотом02
SELECT row_number() over (ORDER BY f1, f2), f1, f2 FROM t
ORDER BY f1, f2 LIMIT 10;
row_number | f1 | f2
------------+----+-------
1 | 0 | 39213
2 | 0 | 86085
3 | 1 | 4750
4 | 1 | 10391
5 | 1 | 13418
6 | 1 | 13960
7 | 1 | 15210
8 | 1 | 54074
9 | 1 | 63252
10 | 2 | 11866
36. dataegret.com
Описание проблемы03
Query with ORDER BY f2, f1 LIMIT N
But only INDEX ON (f1, f2) available with low distnct f1
By default – seq scan + sort
Lets try creatve approach to get beter results
37. dataegret.com
Подготовка данных03
CREATE TABLE t AS SELECT
id,
(Random()*1000)::integer AS f1,
(Random()*100000)::integer AS f2,
'some very boring payload text ...'::text AS payload
FROM generate_series(1,1000000) AS g(id);
CREATE INDEX t_f1_key ON t(f1, f2);
VACUUM ANALYZE t;
39. dataegret.com
EXPLAIN ANALYZE03
Limit (actual rows=2 loops=1)
-> Sort (actual rows=2 loops=1)
Sort Key: f2, f1
Sort Method: top-N heapsort Memory: 35kB
-> Seq Scan on t (actual rows=1000000 loops=1)
Execution time: 574.482 ms
40. dataegret.com
Альтернативная реализация03
WITH RECURSIVE
--iterating over possible f1 values
rec AS (
--start from minimal f1
SELECT min(f1) AS f1 FROM t
UNION ALL
--looking for next f1
SELECT (SELECT min(f1) FROM t WHERE t.f1>rec.f1)
FROM rec WHERE rec.f1 IS NOT NULL
)
--return found values
SELECT _t1.* FROM rec,
LATERAL (SELECT * FROM t WHERE f1=rec.f1 ORDER BY f2 LIMIT 2) AS _t1
ORDER BY _t1.f2, _t1.f1 LIMIT 2;
41. dataegret.com
EXPLAIN ANALYZE03
Limit (actual rows=2 loops=1)
CTE rec
-> Recursive Union (actual rows=1002 loops=1)
-> Result (actual rows=1 loops=1)
InitPlan 2 (returns $1)
-> Limit (actual rows=1 loops=1)
-> Index Only Scan using t_f1_key on t t_2 (actual rows=1 loops=1)
Index Cond: (f1 IS NOT NULL)
-> WorkTable Scan on rec rec_1 (actual rows=1 loops=1002)
Filter: (f1 IS NOT NULL)
-> Limit (actual rows=1 loops=1001)
-> Index Only Scan using t_f1_key on t t_1 (actual rows=1 loops=1001)
Index Cond: (f1 > rec_1.f1)
-> Sort (actual rows=2 loops=1)
Sort Key: t.f2, t.f1
-> Nested Loop (actual rows=2002 loops=1)
-> CTE Scan on rec (actual rows=1002 loops=1)
-> Limit (actual rows=2 loops=1002)
-> Index Scan using t_f1_key on t (actual rows=2 loops=1002)
Index Cond: (f1 = rec.f1)
Execution time: 18.790 ms
45. dataegret.com
Под капотом03
--смотрим следующее уникальное значение f1
SELECT (SELECT min(f1) FROM t WHERE t.f1>rec.f1) AS f1
FROM rec WHERE rec.f1 IS NOT NULL
предыдущий f1=0, получили f1=1
f1
------
0
1
2
…
1000
46. dataegret.com
Под капотом03
--смотрим следующее уникальное значение f1
SELECT (SELECT min(f1) FROM t WHERE t.f1>rec.f1 ) AS f1 FROM
rec WHERE rec.f1 IS NOT NULL
предыдущее f1=1, получили f1=2
f1
------
0
1
2
…
1000
47. dataegret.com
Под капотом03
--rinse and repeat 1000 раз
SELECT (SELECT min(f1) FROM t WHERE t.f1>rec.f1) AS f1 FROM
rec WHERE rec.f1 IS NOT NULL
предыдущий f1=999, получили f1=1000
f1
------
0
1
2
…
1000
48. dataegret.com
Под капотом03
– последний проход цикла
SELECT (SELECT min(f1) FROM t WHERE t.f1>rec.f1) AS f1 FROM
rec WHERE rec.f1 IS NOT NULL
previous f1=1000, now we have f1=NULL
f1
------
0
1
…
1000
Nothing
51. dataegret.com
Под капотом03
--и выбираем для них нужные f2
LATERAL (SELECT * FROM t WHERE f1=rec.f1 ORDER BY f2 LIMIT 2)
rec.f1=0
f1 | f2
----+------
0 | 422
0 | 1321
0 | 1891
0 | 3216
0 | 3533
52. dataegret.com
Под капотом03
--и выбираем для них нужные f2
LATERAL (SELECT * FROM t WHERE f1=rec.f1 ORDER BY f2 LIMIT 2)
rec.f1=1 и так далее до окончания списка f1
f1 | f2
----+------
1 | 2475
1 | 2490
1 | 2722
1 | 2921
1 | 7123
53. dataegret.com
Под капотом03
--loop over all DISTINCT f1 values from rec
LATERAL (SELECT * FROM t WHERE f1=rec.f1 ORDER BY f2 LIMIT 2)
rec.f1=1000
f1 | f2
------+-------
1000 | 1313
1000 | 1530
1000 | 6125
1000 | 7108
1000 | 13199
54. dataegret.com
Под капотом03
–- результат 2000 строк… 2 минимальных f2 для каждого
уникального значения f1:
f1 | f2
------+-------
0 | 422
0 | 1321
1 | 2475
1 | 2490
…
1000 | 1313
1000 | 1530
55. dataegret.com
Под капотом03
--сортируем что получилось и возвращаем итог
SELECT _t1.* FROM rec,
LATERAL (SELECT * FROM t WHERE f1=rec.f1 ORDER BY f2 LIMIT 2) AS _t1
ORDER BY _t1.f2, _t1.f1 LIMIT 2;
f1 | f2
------+-------
117 | 3
841 | 3
56. dataegret.com
Под капотом03
Оценочная сложность: COUNT(DISTINCT f1)*(requested LIMIT)
В нашем случае 1.000*2=2.000 vs 1.000.000.
Производительность с разными LIMIT:
LIMIT | NORMAL | CUSTOM
-----------------------------------
1 | 311ms | 21ms
10 | 325ms | 22ms
100 | 339ms | 60ms
1000 | 350ms | 533ms
58. dataegret.com
Выводы04
Самый короткий запрос на SQL – далеко не всегда самый быстрый
Зачастую проще оказывается переписать вдумчиво запрос чем
начинать созавать новый индекс на 1Tb+ таблице (и смотреть где
можно купить еще пару дисков Intel Optane)
Sql очень гибкий язык с почти неограниченной гибкостью,
пользуйтейсь этим.