{"id":43191,"date":"2016-12-15T15:50:38","date_gmt":"2016-12-15T10:20:38","guid":{"rendered":"http:\/\/www.tothenew.com\/blog\/?p=43191"},"modified":"2016-12-15T15:50:38","modified_gmt":"2016-12-15T10:20:38","slug":"how-to-reduce-the-number-of-druid-segments","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/how-to-reduce-the-number-of-druid-segments\/","title":{"rendered":"How to Reduce the Number of Druid Segments?"},"content":{"rendered":"<p>We have been using <a title=\"Druid\" href=\"http:\/\/druid.io\/\" target=\"_blank\">Druid<\/a> in our project for a while and had <a title=\"Our experience through GIDS16 in Bengaluru\" href=\"http:\/\/www.tothenew.com\/blog\/our-experience-through-gids16-in-bengaluru\/\" target=\"_blank\">shared our experiences during GIDS<\/a>.\u00a0It has given us great results\u00a0as it powers our real-time dashboards, reports on\u00a0running Ad campaigns and provides real-time data to make quick decisions. But like any other databases there will be times when it needs to be optimized. This is similar to how we may optimize various things in MySQL, Oracle or any other database.<\/p>\n<h3>The Problem<\/h3>\n<p>Druid stores all of its data\u00a0sharded by time, data sources and optionally by other dimensions. In Druid terminology this sharded data is called <strong>segments<\/strong>. These segments\u00a0are\u00a0served by Druid&#8217;s\u00a0historical node. For serving all of these segments\u00a0the historical node needs to open\u00a0file handlers to all\u00a0the segments. The problem occurs as the\u00a0amount of data increases then the number of memory mapped files\u00a0will also keep on increasing and there is a limit on the\u00a0memory mapped files on Linux.<\/p>\n<p>We had reached a point where we had more than 140k+ segments which was pushing towards this limit although we had distributed the data across historical nodes in the cluster.\u00a0So we had to somehow reduce the number of segments on each node or the overall of segments in our Druid. Less number of segments has other benefits also as there would be less references in zookeeper and the coordinator node of Druid will have to balance less\u00a0number of segments.<\/p>\n<h3>Initial Solutions Considered<\/h3>\n<ul>\n<li><strong><em>Do Not Load Old Historical Data<\/em><\/strong>\u00a0&#8211; In case\u00a0we could not come up with something good enough this was\u00a0the\u00a0last resort.\u00a0The consideration would have been that from a business perspective do we really need to keep the data\u00a0that was 2 years old or maybe even a year old? For taking this decision, a discussion with the product team would be necessary. We could keep the backup of the data in our deep storage (S3) but configure Druid to not actually\u00a0load the old data. This could be done by\u00a0configuring a drop rule in Druid&#8217;s coordinator console.<\/li>\n<li><strong><em>Merge Smaller Segments<\/em><\/strong> &#8211;\u00a0As Druid shards the data by timestamp and\u00a0datasource we end up with many segments of really small size. This could be easily checked via Druid&#8217;s coordinator console. We had segments of 1 KB, 10 KB etc. Was this really optimal? Not really !!.<br \/>\n<a href=\"http:\/\/druid.io\/docs\/latest\/design\/segments.html\" target=\"_blank\">Druid&#8217;s recommendation<\/a> is that all segments should be in 300 to 700 mb. So we thought that we should\u00a0merge the smaller segments into\u00a0larger segments.<\/li>\n<li><strong><em>More Smaller Machines For Historical Nodes<\/em><\/strong> &#8211; This one can be used to distribute the load across machines and take care of\u00a0limit on memory mapped files. But we would hit that eventually.<\/li>\n<\/ul>\n<h3>Exploration that Led to the Final Solution<\/h3>\n<p>Needless to say merging seems the best option as that takes our storage in the recommended range and for the other 2 options\u00a0they may not be feasible from a business or economic perspective.<\/p>\n<p>We went through\u00a0<a href=\"http:\/\/druid.io\/docs\/0.9.0\/ingestion\/tasks.html#merge-task\" target=\"_blank\">Druid&#8217;s merge task<\/a>\u00a0\u00a0but found that doing it on scale would be problematic as\u00a0the details\u00a0required were a bit too much for a simple thing &#8211; merge the existing segments\u00a0to the recommended size.\u00a0We would have to go through Sruid&#8217;s\u00a0metastore to get segment metadata, add aggregations which were different for all datasources, submit merge and then ensure that the old ones were\u00a0dropped via drop tasks.<\/p>\n<p>After some further exploration and discussions on Druid groups we found that this\u00a0is something which is already present as a configuration option in <a href=\"http:\/\/druid.io\/docs\/0.9.0\/configuration\/coordinator.html#coordinator-operation\" target=\"_blank\">coordinator\u00a0configuration<\/a>\u00a0but turned off by default.<\/p>\n<p>[code]<\/p>\n<p>druid.coordinator.merge.on<\/p>\n<p>[\/code]<\/p>\n<p>This configuration if turned on would do exactly what we want. Although for this to work we need to\u00a0spin up and keep Overlord and Middle manager nodes running which we had not been doing so far.<\/p>\n<h3>Considerations While Implementing<\/h3>\n<ul>\n<li>\u00a0While\u00a0testing this configuration we found that\u00a0this was a CPU intensive task and\u00a0each of the merge task peons would also require enough RAM (2g is default). \u00a0This meant that we needed to strike a balance between how\u00a0long we\u00a0could wait for our backlog of merging to be cleared vs. how\u00a0big machines we were willing to use.<\/li>\n<li>If we started too many middle manager peons then overlord and middle manager&#8217;s memory usage also went up.<\/li>\n<li>Final Size of segments &#8211; Although Druid&#8217;s recommended segment size if 300 &#8211; 700 mb and by default coordinator merges it to a size around 500 mb which is in this range it may not be optimal for all cases. This was found after in-house bench-marking based on the queries that were common for our\u00a0use case.\u00a0The segment size\u00a0to which coordinator will try and merge the smaller segments into depends on a setting that can be changed via\u00a0coordinator console\u00a0mergeBytesLimit. More details can be found <a href=\"http:\/\/druid.io\/docs\/0.9.0\/configuration\/coordinator.html#dynamic-configuration\" target=\"_blank\">here<\/a><\/li>\n<\/ul>\n<p>So while turning this auto-segment merge feature of Druid&#8217;s coordinator console is good for stability, \u00a0be aware that you will have to tune the memory usage of various nodes, decide on number of peons for merging and find\u00a0the segment size that works for your use case by benchmarking for the queries that are used in your system.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>We have been using Druid in our project for a while and had shared our experiences during GIDS.\u00a0It has given us great results\u00a0as it powers our real-time dashboards, reports on\u00a0running Ad campaigns and provides real-time data to make quick decisions. But like any other databases there will be times when it needs to be optimized. [&hellip;]<\/p>\n","protected":false},"author":161,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":23},"categories":[1],"tags":[4843,4859,4292,4294,4293,477],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/43191"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/161"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=43191"}],"version-history":[{"count":0,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/43191\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=43191"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=43191"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=43191"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}