我有一个列updated_at
的表,这是一个排序键。在桌面上同时运行VACUUM
和ANALYZE
后,这是我在updated_at
上过滤时获得的查询计划:
EXPLAIN
SELECT *
FROM my_table
WHERE updated_at > '2018-01-01';
QUERY PLAN
XN Seq Scan on my_table (cost=0.00..0.00 rows=1 width=723)
Filter: (updated_at > '2018-01-01 00:00:00'::timestamp without time zone)
我的理解是,尽管有排序键,查询执行引擎正在对表进行顺序扫描,因此排序键没有做任何事情?
答案 0 :(得分:3)
查看Redshift文档中的"Analyzing the Query Summary" section。它显示了如何使用SVL_QUERY_SUMMARY
视图观察每个查询执行的非常详细的指标。
对于最有效排序密钥用法,您应该会看到rr_scan
(范围限制扫描)列设置为t
且num_rows_pre_filter
应该非常接近至rows
计数。 num_rows_pre_filter
是应用谓词过滤器之前从磁盘扫描的行数。注意:在这种情况下,“相当接近”会因您的具体数据而异。
SELECT stm,seg,step,TRIM(LEFT(label,30))"label"
,rows_pre_filter,rows,avgtime,bytes,is_rrscan
FROM svl_query_summary
WHERE query = 123456
ORDER BY stm ,seg ,step;
| stm | seg | step | label | rows_pre_filter | rows | avgtime | bytes | is_rrscan |
|-----|-----|------|-------------------------------|-----------------|------|---------|-------|-----------|
| 0 | 0 | 0 | scan tbl=428142 name=my_tbl | 103665 | 6 | 52814 | 1273 | t |
| 0 | 0 | 1 | project | 0 | 6 | 52814 | 0 | f |
| 0 | 0 | 2 | sort tbl=303 | 0 | 6 | 52814 | 1288 | f |
| 1 | 1 | 0 | scan tbl=303 name=Internal | 0 | 6 | 74 | 1288 | f |
| 1 | 1 | 1 | return | 0 | 6 | 74 | 0 | f |
| 1 | 2 | 0 | merge | 0 | 0 | 275 | 0 | f |
| 1 | 2 | 1 | project | 0 | 6 | 275 | 0 | f |
| 1 | 2 | 2 | return | 0 | 6 | 275 | 1387 | f |
答案 1 :(得分:2)
顺序扫描在Amazon Redshift上完全正常,因为它不使用索引。
系统非常智能,可以跳过块不包含所需的值,因为每个块(只包含一列的数据)存储块中每个值的最小值和最大值。因此,将自动跳过包含2018-01-01
之前所有日期的块。
这不会出现在EXPLAIN计划中,因为它取决于每个块中存储的实际数据。
最好的办法是运行一些测试,看看它是否正在快速运行,正如您所期望的那样。您可能希望运行SET enable_result_cache_for_session TO OFF
以阻止缓存影响结果。
此外,尽量避免将SORT KEY转换为其他类型的情况。在上面的示例中,如果列是DATE但查询将其用作TIMESTAMP,则它可能无法跳过块,因为它必须在从磁盘读取后转换值。因此,如果WHERE使用完全相同的数据类型,它可能会更好。