мелкое — крупно,
в глубоком разговоре
мудрость приходит
по вопросам сюда: @aigul_sea
Post #102
1.93K
ДА @data_engineerette
Showing posts older than #104 · Back to latest


'id'.desc()
sort vs orderBy - что вам больше нравится, никакой разницыF.col().desc()df.orderBy(F.col('id').desc())ascending=Falsedf.orderBy('id', ascending=False)
df.orderBy(F.col('id'), ascending=False)F.desc()df.orderBy(F.desc('id'))
df.orderBy(F.desc(F.col('id')))spark.sqlspark.sql('select * from my_table order by id desc')SELECT *, а не только нужные поля - вдруг они пригодятся в будущем? И никаких LIMIT - мы не хотим делать выводы на крошечной выборкеON, WHERE и т.д. - лучше сделайте побыстрее и идите отдыхатьOR, не пытайтесь заменить на IN, UNION и т.д.DISTINCT, он должен быть в каждом подзапросе - для нашей 200% уверенностиUPPER, LOWER, LEFT, RIGHT... Ну а WHERE UPPER(name) LIKE '_Mary%'- вообще песня!

--это одинаковые условия
BETWEEN '2024-02-24' AND '2024-02-25'
BETWEEN '2024-02-24 00:00:00' AND '2024-02-25 00:00:00'
CREATE TABLE dates (
`datetime` datetime('UTC')
)
ENGINE = MergeTree()
ORDER BY datetime;
INSERT INTO dates VALUES
('2024-02-23 20:59:00'), ('2024-02-23 21:00:00'), ('2024-02-23 23:59:00'), ('2024-02-24 00:00:00'), ('2024-02-24 02:59:00'), ('2024-02-24 20:59:00'), ('2024-02-24 21:00:00'), ('2024-02-24 22:00:00'), ('2024-02-25 00:00:00'), ('2024-02-25 02:59:00');
SELECT
toDateTime(`datetime`, 'Europe/Moscow'),
CASE
WHEN toDateTime(`datetime`, 'Europe/Moscow') BETWEEN '2024-02-24' AND '2024-02-25' THEN 1
ELSE 0
END AS flag
FROM dates
ORDER BY 1;


Nested Loop/Cartesian ProductHash Join/SortMergeJoin
--1
SELECT *
FROM table1 t1
JOIN table2 t2
ON t1.id = t2.id or t1.name = t2.name;
--2
SELECT *
FROM table1 t1
JOIN table2 t2
ON t1.id = t2.id
UNION ALL
SELECT *
FROM table1 t1
JOIN table2 t2
ON t1.name = t2.name;
CREATE TABLE web.visits (
visitid int,
url string
)
PARTITIONED BY (dt string)
STORED AS PARQUET;
CREATE EXTERNAL TABLE web.visits (...)
ALTER TABLE web.visits SET TBLPROPERTIES('transactional'='false');hdfs://data/web/visits/ - вся таблицаhdfs://data/web/visits/visit_date=2024-03-01 - конкретная партицияspark.table("web.visits")
.select(max("visit_date"))
.show() spark.sql("SHOW PARTITIONS web.visits")
.select(max("partition"))
.show()+----------+
|partition |
+----------+
|2024-03-01|
|2024-02-26|
+----------+
SELECT *
FROM test (NOLOCK)
NOLOCK убирает блокировки, связанные с параллельным обращением к одним и тем же данным. Другое название - READ UNCOMMITTED, т.е. нам не нужно ждать, пока транзакция завершится. Но тут возникает вопрос с чтением грязных данных - мы можем работать с данными, которые уже сто раз изменились.
where(), withColumn(), union(). Например, чтобы отфильтровать строки, нам не нужно знать весь датасет. Мы берем одну строку, применяем условие - готово.join(), groupBy(), sort(), distinct(). Здесь же нам нужен весь датасет. Допустим, мы хотим сделать дистинкт по полю color: на первом экзекьюторе лежат red, blue, green, на втором yellow, violet, blue. Если брать отдельно каждый экзекьютор, то цвета уникальны, но если мы возьмем все, то будут дубликаты. То есть нам сначала надо одинаковые значения собрать (это и есть шафл) и только потом почистить.
df.explain()
F.col('df1.id') == F.col('df2.id')shuffle - группируются одинаковые ключи из разных экзекьюторов на одном => большие расходы на сеть. Но если у нас есть маленькая табличка (десятки мегабайт, но по умолчанию просто 10), то мы можем скопировать ее на все экзекьюторы, поджойнить там же и избежать шафла. Лимит на размер - память самого экзекьютора.# 2й аргумент - размер в МБ
.config('spark.sql.autoBroadcastJoinThreshold', 100)
# так отключается broadcast
.config('spark.sql.autoBroadcastJoinThreshold', -1)
# broadcast join
df1.join(F.broadcast(df2), condition, join_type)
CROSS JOIN LATERAL, LEFT JOIN LATERAL. Так что с другими бд, я надеюсь, тоже несложно разобраться.CREATE FUNCTION getBookByAuthorId(@AuthorId int)
RETURNS TABLE AS RETURN
(
SELECT * FROM book
WHERE author_id = @AuthorId
)
SELECT a.author_name, b.book_name, b.price
FROM author a
CROSS APPLY getBookByAuthorId(a.id) b
--outer apply
SELECT a.author_name, book_list
FROM author a
OUTER APPLY (
SELECT STRING_AGG(book_name, ', ') AS book_list
FROM book b
WHERE b.author_id = a.id
) sub
--подзапрос
SELECT a.author_name, (
SELECT STRING_AGG(book_name, ', ')
FROM book b
WHERE b.author_id = a.id
) AS book_list
FROM author a
--STRING_AGG соединяет строки в одну ячейку с разделителем
SELECT a.author_name, count(book_id) as book_num
FROM author a
OUTER APPLY (
SELECT b.id as book_id
FROM book b
WHERE b.author_id = a.id
) sub
GROUP BY a.author_name

df = df1.join(df2, F.col('id') == F.col('parent_id'), 'left')df = df1.alias('df1').join(df2.alias('df2'), F.col('df1.id') == F.col('df2.id'), 'left').config("spark.sql.crossJoin.enabled", True)