我目前正在与星展在雪花,我有一个性能问题。
在我的查询中,我需要从包含其他表外键的主表中检索100行数据。主表大小介于50k-300k行之间。
这个主表包含类型为number(38,0)的id(外键),这些字段/列的描述是通过直接的内部联接从其他表中检索的。
辅助表(表1、表2……)非常小,所有表的行数都不到20行,只有一个表的行数在1500行左右(仍然非常小)
问题是:
运行查询(如下所示)平均需要1.7秒才能完成。如果删除所有desc字段(使用内部联接检索)和所有内部联接,则查询平均需要300毫秒才能完成。
我的同行实施的当前解决方案:
他们缓存了我们应用程序中所有辅助表的信息(用java制作,但这是不相关的)。对于大约80%的情况(参见下面的查询),我们不需要按描述过滤,这是可行的,但是对于其他20%的情况,我们仍然需要执行内部连接。
缩小解决方案的规模:
不是一个坏的解决方案,但它有两个问题:
(还不错)它膨胀了我们的代码库,基本上是一个java的“连接”
有20%的时间我们需要通过描述进行过滤,我们仍然需要进行内部连接,因此我们仍然存在性能问题。
我想到的一种可能性是将这些表缓存在sf中,但我还没有找到一种直接的方法。也许有一种方法可以优化查询,但我还不了解snowflake在内部是如何工作的,据我所知,它不使用索引,至少与其他平台不一样。
那么,有没有一种方法可以为100%的案例优化sf中的查询?
SELECT
main_table.ONE_ID,
main_table.TWO_ID,
main_table.THREE_ID,
main_table.FOUR_ID,
main_table.FIVE_ID,
main_table.SIX_ID,
main_table.SEVEN_ID,
field_one.ONE_DESC,
field_two.TWO_DESC,
field_three.THREE_DESC,
field_four.FOUR_DESC,
field_five.FIVE_DESC,
field_six.SIX_DESC,
field_seven.SEVEN_DESC
FROM
SOME_DATABASE.MAIN_TABLE AS main_table
INNER JOIN SOME_DATABASE.TABLE_ONE AS table_one ON main_table.field_one_id = table_one .ONE_ID
INNER JOIN SOME_DATABASE.TABLE_TWO AS table_two ON main_table.field_two_id = table_two .TWO_ID
INNER JOIN SOME_DATABASE.TABLE_THREE AS table_tree ON main_table.field_tree_id = table_tree .THREE_ID
INNER JOIN SOME_DATABASE.TABLE_FOUR AS table_four ON main_table.field_four_id = table_four .FOUR_ID
INNER JOIN SOME_DATABASE.TABLE_FIVE AS table_five ON main_table.field_five_id = table_five .FIVE_ID
INNER JOIN SOME_DATABASE.TABLE_SIX AS table_six ON main_table.field_six_id = table_six .SIX_ID
INNER JOIN SOME_DATABASE.TABLE_SEVEN AS table_seven ON main_table.field_seven_id = table_seven .SEVEN_ID
WHERE
main_table.ONE_ID IN (25, 26)
AND main_table.TWO_ID IN (10, 12)
AND main_table.THREE_ID IN (1, 2, 3)
AND main_table.FOUR_ID IN (2, 3)
AND main_table.FIVE_ID IN (3)
AND main_table.SEVEN_ID IN (1)
-- The following WHERE clauses are present in about 20% of the queries
AND table_one.ONE_DESC,
AND table_two.TWO_DESC,
AND table_three.THREE_DESC,
ORDER BY
main_table.ONE_ID,
main_table.TWO_ID,
main_table.THREE_ID
LIMIT
100 OFFSET 0
小更新:
我一直在尝试使用with子句,包括 Package ID和描述,但似乎没有改进
3条答案
按热度按时间envsm3lx1#
我只是好奇,如果您使用子查询中主表上的筛选来表达查询,是否会有所不同:
巨大的可伸缩性的缺点之一是,所使用的方法会给较小的查询增加开销。也就是说,如果将表的大小乘以1000,查询可能只需要几秒钟——但这并不能帮助您在较小的数据上缩短时间。
chy5wohz2#
你有没有试过重新设计你的字典表?就像你有一个:
dt1、dt2、dt3各有键、值
你可以试着把它变成
dt dictionary\u id、key、value
这一次不是5个小表,而是1个稍微大一点、稍微复杂一点的连接条件,因为您必须为每个表添加字典id,但所有表都可能在单个数据块而不是5个数据块中进行检索
7rfyedvj3#
我的第一个想法是,snowflake的设计不是为了快速提出这样的小问题,而是为了回答大问题。因此,对我来说1.xs是很好的响应时间。
但考虑到你想快点。。
我首先检查慢速查询的编译时间是否与快速查询的编译时间相同。因为如果您的表是碎片化的,则需要读取更多的元数据。
接下来,我将查看执行的概要,看看时间花在了哪里。过去我们发现
比…快
噢,我们发现gordon在select from a table时显式地放置where子句,这有助于解决优化器的困惑。
但另一方面可能只是额外的数据传输到客户机所需的时间更长(如果您使用客户机时间作为判断标准),或者如果您查看webui中的性能,您读取的数据越多,运行查询所需的时间就越长。所以即使你建了一个新表
然后再做
所需时间将超过:
最后,我知道它是示例代码,但是从
main_table
至main_table
因为这是已经存在的别名/名称。