The MemSQL query optimizer

Jack Chen, Samir Jindel, Robert Walzer, Rajkumar Sen, Nika Jimsheleishvilli, Michael Andrews
2016 Proceedings of the VLDB Endowment  
Real-time analytics on massive datasets has become a very common need in many enterprises. These applications require not only rapid data ingest, but also quick answers to analytical queries operating on the latest data. MemSQL is a distributed SQL database designed to exploit memory-optimized, scale-out architecture to enable real-time transactional and analytical workloads which are fast, highly concurrent, and extremely scalable. Many analytical queries in MemSQL's customer workloads are
more » ... r workloads are complex queries involving joins, aggregations, subqueries, etc. over star and snowflake schemas, often ad-hoc or produced interactively by business intelligence tools. These queries often require latencies of seconds or less, and therefore require the optimizer to not only produce a high quality distributed execution plan, but also produce it fast enough so that optimization time does not become a bottleneck. In this paper, we describe the architecture of the MemSQL Query Optimizer and the design choices and innovations which enable it quickly produce highly efficient execution plans for complex distributed queries. We discuss how query rewrite decisions oblivious of distribution cost can lead to poor distributed execution plans, and argue that to choose high-quality plans in a distributed database, the optimizer needs to be distribution-aware in choosing join plans, applying query rewrites, and costing plans. We discuss methods to make join enumeration faster and more effective, such as a rewrite-based approach to exploit bushy joins in queries involving multiple star schemas without sacrificing optimization time. We demonstrate the effectiveness of the MemSQL optimizer over queries from the TPC-H benchmark and a real customer workload. Project [s2 / 7.0 AS avg_yearly] Aggregate [SUM(1) AS s2] Gather partitions:all Aggregate [SUM(lineitem_1.l_extendedprice) AS s1] Filter [lineitem_1.l_quantity < s_avg] NestedLoopJoin |---IndexRangeScan lineitem AS lineitem_1, | KEY (l_partkey) scan:[l_partkey = p_partkey] Broadcast HashGroupBy [AVG(l_quantity) AS s_avg] groups:[l_partkey] NestedLoopJoin |---IndexRangeScan lineitem, | KEY (l_partkey) scan:[l_partkey = p_partkey] Broadcast Filter [p_container = 'LG PACK' AND p_brand = 'Brand#43'] TableScan part, PRIMARY KEY (p_partkey)
doi:10.14778/3007263.3007277 fatcat:gbbm7sr6e5gnfiq2q4jrhimqs4