<@U0A71G31CDV> Give me your opinion on this MV def...
# questions-and-troubleshooting
m
@Rocky Give me your opinion on this MV definition CREATE MATERIALIZED VIEW requests.mv_pkg_avails_nobids PARTITION BY hour_start DISTRIBUTED BY HASH(package_id) ORDER BY (package_id) REFRESH ASYNC EVERY (INTERVAL 10 MINUTE) PROPERTIES ( "auto_refresh_partitions_limit" = "3", "partition_refresh_number" = "1" ) AS SELECT date_trunc('hour', received) AS hour_start, pid AS package_id, property_id, media_owner_id, country, region, CONCAT(',', array_join(array_sort(array_distinct(formats)), ','), ',') AS format_set, SUM(num_requests) AS n FROM requests.requests, unnest(array_distinct(inventory_package_ids)) AS t(pid) WHERE has_bid = 0 GROUP BY hour_start, package_id, property_id, media_owner_id, country, region, format_set; Base table is distributed by auction_id and ordered by (received, auction_id)
r
This is a well-structured Materialized View (MV) definition for handling "exploded" array data and optimizing for high-concurrency lookups on specific IDs (
package_id
). Here is a breakdown of the strengths and some points to consider: 1. Partitioning & Incremental Refresh * Strengths: You are using
PARTITION BY hour_start
derived via
date_trunc('hour', received)
. StarRocks 2.5+ supports this "partition rollup" pattern. This allows the MV to perform incremental partition-level refreshes. If only the latest hour of data changes in the base table, StarRocks will only refresh that specific hour in the MV, rather than the whole dataset. * Note: Ensure the base table
requests.requests
is also partitioned by
received
. If the base table isn't partitioned, StarRocks cannot track changes at the partition level, and every refresh will scan the entire base table. 2. Distribution and Sorting * Strengths: The base table is sorted by
(received, auction_id)
. By defining the MV with
DISTRIBUTED BY HASH(package_id)
and
ORDER BY (package_id)
, you are essentially creating a secondary index. Queries that filter or join on
package_id
will be significantly faster because StarRocks can leverage prefix index scanning and data locality. 3. Refresh Properties *
auto_refresh_partitions_limit = 3
: This is a safe "guardrail." It ensures that a single automatic refresh trigger won't try to refresh more than 3 partitions at once. This is great for preventing resource spikes if you have a backfill or a large late-data arrival. *
partition_refresh_number = 1
: This forces StarRocks to refresh partitions one by one. This is the safest setting for memory management (prevents OOM during refresh) but might make the total refresh time longer if you often have many partitions to update. * Refresh Interval:
EVERY (INTERVAL 10 MINUTE)
is a reasonable trade-off between data freshness and system load. 4. Query Logic (Unnesting) * Performance: Using
unnest(array_distinct(inventory_package_ids))
in the
FROM
clause effectively flattens the data. This is much more efficient to query than using
array_contains
on the base table. * Complexity: The
CONCAT(..., array_join(array_sort(array_distinct(formats)), ','), ...)
logic is quite heavy. Since this is materialized, you pay the compute cost once during refresh rather than at query time, which is exactly what MVs are for. Potential Considerations 1. Late Data &
auto_refresh_partitions_limit
: If data arrives late for more than 3 distinct hours, the limit of
3
means the MV might stay "stale" for the older partitions until the next refresh cycles catch up. If you expect frequent late-data arrivals spanning many hours, you might need to increase this limit or use a
partition_ttl
. 2. Query Rewrite: While this MV will be great for direct queries, Transparent Query Rewrite (where StarRocks automatically routes a query on the base table to the MV) might be limited because of the
unnest
and complex array transformations. You should check if
EXPLAIN
shows the query using the MV. If not, you may need to query the MV directly by name. 3. Storage: Because of the
unnest
, the number of rows in this MV will likely be significantly larger than the base table (proportional to the average size of
inventory_package_ids
). Monitor the disk usage. Recommendation The definition is optimal for performance on
package_id
lookups. If your primary goal is to speed up reports filtered by
package_id
or
format_set
, this is the correct approach. One minor tweak: If you are on StarRocks 3.1+, consider adding a
partition_ttl
(e.g.,
"partition_ttl" = "1 month"
) to automatically drop old MV partitions and save space, rather than letting it grow indefinitely. References