Hi All, If we set a broadcast forever rule for a t...
# general
a
Hi All, If we set a broadcast forever rule for a table, does it push the table down to the historicals as well? Document mentions about brokers not about the historicals. If the retention for a table is set as "broadcast forever", would a direct join with it run directly on the historical rather than pulling in the data to the broker to perform the join? We are looking to improve the join performance in native queries as opposed to repeated re-ingestion to write the updated data. Separately, I chanced upon the below article on "indexed tables" in Druid. Is this something that has been abandoned? https://support.imply.io/hc/en-us/articles/360051201993-Druid-indexed-tables-alpha Thanks, AR.
j
I've opted for a loadForever rule with replicas equal to the total number of data nodes.
We did that because broadcastForever is marked with "don't use in production"
I should have explained the use case. We only use loadForever (all replicas) with tables that are infrequently updated and always used in joins. These tables tend to be things like country code data, location (geo) data, etc... The data all fits in a single segment (under 5MM rows). We considered lookup tables but a datasource is significantly easier to work with. I've not deeply tested this. Using broadcastForever rules seem to fit our need but we opted not to use it due to a note about it being experimental. It makes sense in that you would be saving any download time from deep storage (and subsequent deletion of the data) but I imagine it's a small savings. Nonetheless it makes sense for us as queries join those datasources all the time.
A note about JOIN in Druid. All datasources (besides the first) get loaded into memory for the join. The best way to improve performance joining two large tables is to limit the scope of the 2nd table. The best practices I follow are: 1. Ensure your largest datasource is the first table 2. Ensure you always join to a subquery on the right-hand-side 3. Always use a WHERE __time clause to limit segments needed 4. Repeat your WHERE clause conditions inside of all subqueries (as applicable) Example:
Copy code
SELECT <columns>
FROM datasource1
INNER JOIN (
  SELECT <columns>
  FROM datasource2
  WHERE __time >= <limit the scope of segments to load>
  AND <other conditions as necessary>
) ON <join parameters>
WHERE __time >= <repeated here to limit the scope of datasource1>
AND <other conditions as necessary>
a
Hi JRob, Thank you for the useful tips. We have a similar use case as you mentioned. Our ref data tables are infrequently updated but need to be used in joins. I set ""loadForever" on all data nodes for one of the tables with ~4.5MM rows. But when I joined a daily table with about 2MM rows per day with this table, it still blew with an error that number of output rows is higher than the "maxSubqueryRows" (1.5MM) limit. What is the "maxSubqueryRows" limit that you have configured? We have since moved to testing using lookups and find the performance quite good. Of course, there is a memory cost to this and I have few questions on that which I will be posting the forum. 🙂 Regards, AR.
j
We use the default maxSubqueryRows of 100K. It's rare that we need to go above that number but in those rare cases where we really can't reduce the number of rows on the right-hand-side then we override the default by passing an override for maxSubqueryRows in the query context. I've never had to use > 1 MM though.
One technique to reduce the number of rows is to use GROUP BY in the subquery,
Generally we try to denormalize our data structures. We are exploring using something along the lines of Apache Spark to pre-join disparate events for Druid consumption.
a
We use Spark to prepare the data and load them into denormalized Druid tables currently. This is where we are stuck due to the absence of updates. If your historical data doesn't need to be updated, then this works very well. We are currently in a never ending loop of historical data updates which is very time consuming.
j
It's best to treat the data as immutable, but you can use compaction or reindex jobs to overwrite previous segments (e.g. summarizing / rolling up data).
I'm hoping that Druid adds support for multiple compaction configurations for this reason. Today we use a cron-like tool to execute such jobs via API.
a
Correct. If the data is immutable, it works very well. If not, then the repeated reindexing can be a big issue.