大家好,
我有20年的數據,600行。
我有分區在年和月生成的一個文件大小似乎是合理的(128 mb)。
查詢所有數據使用時間戳,所有查詢需要過濾的確切時間。
所以我的要求是,當過濾時間戳它隻是訪問一年和月分區相當於時間戳。
這似乎是可行的使用生成的列,根據磚和微軟的文檔。
https://docs.delta.io/latest/delta-batch.html use-generated-columns
https://learn.microsoft.com/en-us/azure/databricks/delta/generated-columns
通常說的一樣的。
DeltaTable.create(火花)\ .tableName (default.events) \ .addColumn (“eventId”、“長整型數字”)\ .addColumn(“數據”、“字符串”)\ .addColumn (“eventType”、“字符串”)\ .addColumn (“eventTime”、“時間戳”)\ .addColumn(“年”、“INT”generatedAlwaysAs =”(eventTime)”) \ .addColumn(“月”,“INT”, generatedAlwaysAs =月(eventTime)) \ .addColumn(“天”、“INT”, generatedAlwaysAs =“天(eventTime)”) \ .partitionedBy (“eventType”、“年”、“月”、“日”)\ . execute ()
火花。sql (' SELECT * FROM違約。事件,eventTime > = " 2020-10-01就是" < =“2020-10-01 12:00:00”)
“三角洲湖自動生成一個分區過濾器,這樣前麵的查詢隻讀取數據分區
年= 2020 /月= 10 /天= 1
即使沒有指定分區過濾器。
你可以使用一個解釋條款並檢查所提供的計劃是否三角洲湖自動生成任何分區過濾器。”
我的問題是,當我使用解釋命令,你可以清楚地看到它不使用partitionfilter。
% sql解釋格式化SELECT * FROM違約。events2 eventTime =“2023-01-01”就是
= = * = =物理計劃項目(4)+ - *過濾器(3)+ - * ColumnarToRow(2) + -掃描鋪違約。events2(1)(1)掃描鋪違約。events2輸出[7]:[eventId # 25670469 l,數據# 25670470,eventTime # 25670472, eventType # 25670471, # 25670473, # 25670474,月日# 25670475)成批的:真正的位置:PreparedDeltaFileIndex [dbfs: / user /蜂巢/倉庫/ events2] PushedFilters: [IsNotNull (eventTime),等於(eventTime, 2023-01-01 00:00:00.0)] ReadSchema: struct < eventId:長整型數字、數據:字符串,eventTime:時間戳> (2)ColumnarToRow [codegen id: 1)輸入[7]:[eventId # 25670469 l,數據# 25670470,eventTime # 25670472, eventType # 25670471, # 25670473, # 25670474,月日# 25670475)(3)過濾器(codegen id: 1)輸入[7]:[eventId # 25670469 l,數據# 25670470,eventTime # 25670472, eventType # 25670471, # 25670473, # 25670474,月日# 25670475)條件:(IsNotNull (eventTime # 25670472)和(eventTime # 25670472 = 25670472就是))(4)項目(codegen id: 1)輸出[7]:[eventId # 25670469 l,數據# 25670470,eventType # 25670471, eventTime # 25670472, # 25670473, # 25670474,月日# 25670475)輸入[7]:[eventId # 25670469 l,數據# 25670470,eventTime # 25670472, eventType # 25670471, # 25670473, # 25670474,月日# 25670475)
好像我有一天,你可以清楚地看到一個分區過濾器。
“PartitionFilters: [isnotnull(# 25670689),(天# 25670689 = 1)”
% sql解釋格式化SELECT * FROM違約。events2 eventTime =“2023-01-01”就是和天= 1
= = * = =物理計劃項目(4)+ - *過濾器(3)+ - * ColumnarToRow(2) + -掃描鋪違約。events2(1)(1)掃描鋪違約。events2輸出[7]:[eventId # 25670683 l,數據# 25670684,eventTime # 25670686, eventType # 25670685, # 25670687, # 25670688,月日# 25670689)成批的:真正的位置:PreparedDeltaFileIndex [dbfs: / user /蜂巢/倉庫/ events2] PartitionFilters: [isnotnull(# 25670689),(# 25670689 = 1天)]PushedFilters: [isnotnull (eventTime),等於(eventTime, 2023-01-01 00:00:00.0)] ReadSchema: struct < eventId:長整型數字、數據:字符串,eventTime:時間戳> (2)ColumnarToRow [codegen id: 1)輸入[7]:[eventId # 25670683 l,數據# 25670684,eventTime # 25670686, eventType # 25670685, # 25670687, # 25670688,月日# 25670689)(3)過濾器(codegen id: 1)輸入[7]:[eventId # 25670683 l,數據# 25670684,eventTime # 25670686, eventType # 25670685, # 25670687, # 25670688,月日# 25670689)條件:(isnotnull (eventTime # 25670686)和(eventTime # 25670686 = 25670686就是))(4)項目(codegen id: 1)輸出[7]:[eventId # 25670683 l,數據# 25670684,eventType # 25670685, eventTime # 25670686, # 25670687, # 25670688,月日# 25670689)輸入[7]:[eventId # 25670683 l,數據# 25670684,eventTime # 25670686, eventType # 25670685, # 25670687, # 25670688,月日# 25670689)
我們在10.4版本,所以這應該是支持。
有人做到了這一點嗎?或者你可以在我的示例中看到任何問題嗎?
最好的問候,
拉姆
@Rasmus Stokholm:
看來你有正確的分區數據基於年和月也定義生成的列,在三角洲表月和日。當您運行一個查詢過濾器eventTime列上,三角洲湖應該自動生成一個分區過濾器根據查詢條件隻和閱讀相關的分區,在三角洲湖解釋文檔。
然而,你提到當你跑一個解釋命令,您沒有看到預期的分區過濾器被應用。在一個案例中,你看到一個分區過濾器過濾時除了eventTime天,但當隻在eventTime過濾。
有一點要注意的是,三角洲湖可以選擇閱讀額外的分區如果它決定將更有效,例如,如果分區大小太小或者檢測到數據傾斜。您可以使用spark.databricks.delta.logLevel配置屬性看到更詳細的日誌和理解為什麼三角洲湖是閱讀某些分區。
另一個可能的原因沒有看到分區過濾器被應用的查詢優化器可能決定使用一個不同的執行計劃,不依賴於分區修剪。在這種情況下,您可能想使用提示語法迫使優化器使用一個特定的執行計劃。
最後,你也可以嚐試在CREATE TABLE語句中使用分區BY子句顯式地定義分區列和確保分區修剪總是使用,因為這是首選的方式來定義分區在三角洲湖。
嗨@Vidula卡納和@Suteja卡努裏人
謝謝你的建議。
但是我還沒有真正的進展。
我把loglevel調試。但我不太確定在哪裏檢查結果。
我沒有找到任何有用的線索,部隊訪問計劃使用分區。
我嚐試創建直接在sql表分區by子句。
但它仍然具有相同的結果。
然後我嚐試切換到使用azure存儲中的三角洲湖通過openrowset並通過突觸連接。
我確認插入18億行和分區。每個文件夾(年,月)3 - 4 10 ~ 30 MB的文件。
sql查詢顯示,當我openrowset沒有年和月和時間戳它掃描大約14 GB。
當我年和月在where子句中它包括掃描。35 mb。
所以它不僅失去了它也花費很多錢由於不必要的掃描。
@Rasmus Stokholm:請讓我知道如果這可以幫助!
很好,你將日誌級別設置為調試,但重要的是要知道日誌寫入所以你可以檢查他們。通常,日誌寫入一個文件在服務器上執行查詢,或者他們可能被發送到一個集中的日誌係統。
關於強製訪問計劃使用的分區,您可以使用
EXPLAIN語句查看查詢計劃生成的數據庫引擎。這會給你洞察如何處理您的查詢引擎和是否使用分區。
當你創建了表的SQL分區BY子句,你也在查詢中指定分區列?例如,如果分區表的年和月,你在WHERE子句中包含那些列在表查詢?
很高興聽說切換到三角洲湖在Azure存儲和使用突觸通過OpenRowset幫助與分區問題。重要的是要優化您的查詢和數據存儲,以避免不必要的掃描,正如你提到的,以減少時間和成本。