Patent Publication Number: US-11030189-B2

Title: Maintaining up-to-date materialized views for time-series database analytics

Description:
CROSS-REFERENCE TO RELATED APPLICATION 
     This application claims the benefit of U.S. Provisional Application No. 62/836,397, filed on Apr. 19, 2019, which is incorporated by reference in its entirety. 
    
    
     INTRODUCTION 
     This disclosure relates generally to efficiently storing, processing, and maintaining materialized views of data in a database system, and in particular to storing, processing, and maintaining such views or data aggregates on time series data in a partitioned database system. 
     Time-series data is generated and processed in several contexts: monitoring and developer operations (DevOps), sensor data and the Internet of Things (IoT), computer and hardware monitoring, fitness and health monitoring, environmental and farming data, manufacturing and industrial control system data, financial data, logistics data, application usage data, and so on. Often this data is high in volume, for example, individual data sources may generate high rates of data, or many different sources may contribute data. Furthermore, this data is complex in nature, for example, a source may provide multiple measurements and labels associated with a single time. The volume of this stored data often increases over time as data is continually collected. Analytical systems typically query this data to analyze the past, present, and future behavior of entities associated with the data. This analysis may be performed for varied reasons, including examining historical trends, monitoring current performance, identifying the root cause of current problems, and anticipating future problems such as for predictive maintenance. As a result, operators are not inclined to delete this potentially valuable data. 
     Conventional systems fail to support the high write rates that are typical of many of these applications, which span across industries. For example, in Internet of Things (IoT) settings including industrial, agricultural, consumer, urban, or facilities, high write rates result from large numbers of devices coupled with modest to high write rates per device. In logistics settings, both planning data and actuals comprise time series that can be associated with each tracked object. Monitoring applications, such as in development and operations, may track many metrics per system component. Many forms of financial applications, such as those based on stock or option market ticker data, also rely on time-series data. All these applications require a database that can scale to a high ingest rate. 
     Further, these applications often query their data in complex and arbitrary ways. Such query patterns may involve fetching or aggregating a single or few metrics across a particular time periods, or involve employing predicates (e.g., complex conjunctions in a WHERE clause), aggregations, statistical functions, windowed operations, JOINs against relational data, subqueries, common table expressions (CTEs), and so forth. Yet these queries need to be executed efficiently. 
     Therefore, storing time-series data demands both scale and efficient queries. Time-series database systems based on partitioned tables for scaling to support high write rates and efficiently handle queries, including through the SQL query language, are described in U.S. Pat. No. 10,073,903 titled, “Scalable Database System for Querying Time-Series Data” and U.S. Pat. No. 10,073,888, titled, “Adjusting partitioning policies of a database system in view of storage reconfiguration”, each of which is fully incorporated by reference herein. 
     One approach for speeding up query performance is to precalculate full or partial answers to the queries. As an example, consider a scenario where a database query wants to know the maximum of a certain value every hour for the past three days. If a database user or admin knows that this type of query to the time-series dataset is common, rather than walking through three days of raw data at query time to compute the hourly max, the database can precalculate each hourly max, and so the query only needs to access these 72 rows of data at query time, rather than the much greater volume of raw data. 
     Such precalculations can also be utilized as partial answers to speed up other queries. Continuing with this example, if a user now asks for the daily max over this same three-day period, the database can either rescan the raw data to compute these three values, or, for each day, it can find the maximum of each of the hourly maximum values. And the database user or operator can then decide when it wants to store these daily maximum values to speed up future queries, or continue to calculate these values at query time. 
     These types of stored calculations or stored results are often called views or materialized views in the database field (two terms that we use interchangeably herein). In general, a materialized view in a database contains the result of a query, e.g., a local copy of remote data, some subset of the rows and/or columns of a table, some computed join result between multiple tables, or a summary using an aggregation function (as in the above example). 
     Databases often use materialized views for performance reasons, such as speeding up response times for aggregation queries performed by the user. By doing part of the work beforehand and caching the results, many aggregate queries can be sped by orders of magnitude or more. Embodiments of the invention process such aggregations as they are used in materialized views. 
     However, difficulties arise when trying to keep some materializations in sync with changes to the underlying data as new inserts, updates, deletes, or other changes occur. In our example, if a new maximum value is inserted into the underlying table that contains the raw, unaggregated data, our current materialization of the maximum value is no longer correct (which we also refer to as being “stale” or “not fresh”, as our knowledge and the materialized view no longer reflects the latest known information). Herein, we also interchangeably refer to a table on which a materialized view is based as the underlying table, the base table, or describe it as the table with raw data. 
     In some situations, database users or operators may find it satisfactory if the materialized aggregate is stale, in which case they do not need to take any further action. At some later point, the database (or some user/operator of the database) can take some action to recompute its materialized view, so that the view becomes fresh and reflects the latest known information. 
     In many other situations, however, database users or operators seek to maintain materialized views that are more up-to-date given their underlying raw data. Thus, conventional techniques fail to provide efficient mechanisms for creating and maintaining continuously up-to-date materialized views for time-series databases. 
     SUMMARY 
     The above and other issues are addressed by a computer-implemented method, computer system, and computer readable storage medium for creating and maintaining continuously up-to-date materialized views for time-series databases, particularly in order to enable faster analytics over large data sets. 
     Embodiments of the method comprise creating a materialized view on a base table and continuously maintaining that view on the table, such that as new inserts, updates, deletes, or other changes are made to the table, the materialized view is correspondingly updated either immediately or lazily. If the materialized view is updated continuously, select or other read queries to the view can just return the data in the view. If the materialized view is updated lazily and the system wants to ensure up-to-date answers, queries to the view may combine data from the view with results calculated at query time on the view&#39;s underlying raw data. 
     To ensure that queries return up-to-date data while operating on materialized views, the database engine employs several different approaches. In one embodiment of this method, the materialized view is updated on every change to the base table. In another embodiment, the database engine marks a region of the materialized view as invalid when a change is made to the base table. When the materialized view is queried, the database engine uses data from the materialized view provided it is not invalid, but for the regions that are marked as invalid, the database engine computes the result from the view&#39;s underlying table at query time. In such cases, the results returned from a query can include data either solely precalculated from the materialized view, solely computed at query time from the base table, or that is a mix of data from the materialized view and computed at query time from the base table. In some embodiments, the database engine uses these computations performed at query time to update the materialized views, while other embodiments update the materialized view only through a separate process or method. 
     In an embodiment of this method, the database engine only materializes some regions of the base table (interchangeable known as portions or ranges of the base table). In such cases, when a query is made against the view, if the query specifies some range that is covered solely by the materialized view, then the results of the query are returned solely through data from the materialized view. Alternatively, if the query specifies some range fully outside the region covered by the materialized view, then the results returned from the query are computed at query time from the underlying base table. Finally, if the query specifies some range that falls both within and outside the region(s) covered by the materialized view, then the results returned from the query is a mix of data from the materialized view and computed at query time from the base table. 
     In some embodiments, regions of tables are defined by time intervals, having a start and end time, such that records within the region have timestamps (or time attribute values) that are between the start and end time (either inclusively or exclusively). Regions may also be defined on additional attributes associated with the tables, including dimension attributes other than time when employing hypertables. In some embodiments, a region may be defined on multiple dimensions, including both by a time interval and by an additional region or range of a different dimension. In some embodiments, a region is defined by some number of records or set of records (contiguous in time based on the records&#39; timestamps); such regions also have a start and end time threshold associated with the region based on the minimum and maximum timestamp of the records that comprise the region. 
     While the above embodiments have been described as the query specifying the materialized view, the database engine can also return materialized data when a query is made against the base table (if the data stored in the materialized view is appropriate for the query). Additionally, the database engine can provide separate names so that queries can expressly specify that only data from the materialized view should be returned, that only data from the underlying base table should be returned, or that the database engine can return a mixture of data from both the materialized view and base table. In such a manner, embodiments of this method enable a single name to be associated with both the materialized table and the base table, as well as a distinct name for only the materialized table and a name for only the materialized table. As we later describe, more complex configurations of materializations are supported, such that materialized tables can be associated with other materialized tables; in such embodiments, a name can then be associated with multiple tables (the base table, the first materialized table associated with the base table, and the second materialized table associated with the first materialized table), or separate names can be associated with each materialized table or different subsets of the tables. 
     While many of the inventive methods described herein are described in terms of a single materialized view and a base table, one of ordinary skill will recognize that a single database can contain many tables, many materialized views, materialized views that are based on, other materialized views, or materialized views based on base tables from other databases. Further, one of ordinary skill will recognize that a database can be organized in many ways, and the described methods herein can be employed in many such configurations, such as a single or multiple database components, a single or multiple processes running on a single physical machine, or multiple physical machines that coordinate together to provide the database system. Different views or tables may be located on different disks or storage media, different physical machines, or views or tables may themselves be spread over multiple physical disks or machines. Further, the materialized view or table, or the base table, described herein can itself be formed by a partitioned table, such that each partition of the view or table corresponds to a certain range or region of the view or table&#39;s data. Examples of such partitioned tables are described in the aforementioned U.S. Pat. No. 10,073,903 and #10,073,888, both fully incorporated by reference herein. Adopting such language from those patents, we interchangeably refer to such partitioned tables as hypertables. A hypertable is partitioned into a plurality of tables, also called chunks, based on the dimension attributes. A chunk is specified using a set of values for each dimension attribute. For each record stored in the chunk, the value of each dimension attribute maps to a value from the set of values for that dimension attribute. A determination is made whether an input record should be stored in a new chunk or an existing chunk. For each new chunk being created, sets of values corresponding to each dimension attribute are determined and the new chunk is created for storing the input record. The hypertable is updated by storing the input record in the new chunk. The data stored in the updated hypertable is processed in response to subsequent queries that identify the hypertable. 
     One of ordinary skill will also recognize while the invention described herein often refers to changes or queries to data, such changes can constitute any data manipulation language (DML) operations (including inserts, updates, upserts, deletes, or any other data modifications), while such queries can include any data query language (DQL) operations (including SELECT-type queries, query parsing, transformation/rewriting, optimization and execution, etc.). Finally, the database system also involves data definition language (DDL) operations, including creating or altering tables, creating or altering indexes, defining views and materializations, as well as other administrative tasks. 
     Embodiments of a computer readable storage medium store instructions for performing the steps of the above method. Embodiments of a computer system comprise one or more computer processors and a computer readable storage medium storing instructions for performing the steps of the above method. 
     The features and advantages described in this summary and the following detailed description are not all-inclusive. Many additional features and advantages will be apparent to one of ordinary skill in the art in view of the drawings, specification, and claims hereof. 
    
    
     
       BRIEF DESCRIPTION OF THE DRAWINGS 
       The teachings of the embodiments can be readily understood by considering the following detailed description in conjunction with the accompanying drawings. 
         FIG. 1  is a block diagram of a system environment in which the database system operates, in accordance with an embodiment. 
         FIG. 2  illustrates partitioning of data of a database table, in accordance with an embodiment. 
         FIG. 3  shows processing of queries in a database system comprising a plurality of database nodes, in accordance with an embodiment. 
         FIG. 4A  shows the system architecture of a query processor, in accordance with an embodiment. 
         FIG. 4B  shows the system architecture of a chunk management module, in accordance with an embodiment. 
         FIG. 5  illustrates the process of inserting records into a hypertable stored across a plurality of database system nodes, in accordance with an embodiment. 
         FIG. 6  is a flowchart of the process of executing a query for processing records stored in a hypertable, in accordance with an embodiment. 
         FIGS. 7 (A-C) illustrate partitioning of data of a database table to adapt to addition of locations to the database system according to an embodiment of the invention. 
         FIG. 8  shows a flowchart illustrating the process of modifying a data partitioning policy of a database system in response to addition of new locations to the database system, in accordance with an embodiment. 
         FIG. 9  illustrates selection of partitioning policy for creating chunks based on time attribute of the record, according to an embodiment. 
         FIG. 10  shows a flowchart of the process for selection of partitioning policy for creating chunks based on time attribute of the record, according to an embodiment. 
         FIG. 11  illustrates selection of partitioning policy for creating chunks based on time of receipt of a record by the database system, according to an embodiment. 
         FIG. 12A  illustrates processing of a query by combining data of a materialized table with base table, according to an embodiment. 
         FIG. 12B  illustrates use of invalidation log to detect regions of the time dimension that have been invalidated for processing queries, according to an embodiment. 
         FIG. 13  shows an architecture of a computer that may be used for implementing a database system node, in accordance with an embodiment. 
     
    
    
     DETAILED DESCRIPTION 
     Embodiments of the invention include a database system that supports a standard query language like SQL and exposes an interface based database tables or on a hypertable that partitions the underlying data across servers and/or storage devices. The database system allows users to interact with data as if it were stored in a conventional database table, hiding the complexity of any data partitioning and query optimization from the user. Embodiments of the database system make a query language like SQL scalable for time-series data. The database system combines the best features of both RDBMS and NoSQL databases: a clustered scale-up and scale-out architecture and rich support for complex queries. Scaling up corresponds to running on larger individual servers, for example, machines with high numbers of CPUs or cores, or servers with greater RAM and disk capacity. Scaling up also includes increasing storage capacity of an existing database system by adding additional storage devices. Scaling out comprises increasing storage capacity of the database system by adding additional servers, for example, by sharding the dataset over multiple servers, as well as supporting parallel and/or concurrent requests across the multiple servers. 
     System Environment 
       FIG. 1  is a block diagram of a system environment in which the database system operates, in accordance with an embodiment. The system environment comprises a database system  110 , one or more client devices  120 , and a network  115 . 
     The database system  110  comprises a query processor  130 , a materialization engine  180 , an invalidation engine  190 , a metadata store  140 , and a data store  145 . The database system  110  may include other components, for example, as illustrated in  FIG. 2 . The database system  110  receives database queries, for example, queries specified using SQL and processes them. The database system  110  may support standard SQL features as well as new user-defined functions, SQL extensions, or even non-SQL query languages such as declarative programming languages, a REST interface (e.g., through HTTP), or others. 
     The data store  145  stores data as tuples (also referred to as records) that may be stored as rows of data, with each row comprising a set of attributes. These attributes typically have a name associated with them (e.g., “time”, “device_id”, “location”, “temperature”, “error_code”) and a type (e.g., string, integer, float, boolean, array, json, jsonb (binary json), blob, geo-spatial, etc.), although this is not necessary in all cases. Attributes may also be referred to herein using the terms “fields”, “columns” or “keys”. 
     The data store  145  may store records in a standard database table that stores data in one or more files using conventional techniques used by relational database systems. The data store  145  may also store data in a partitioned database table referred to as a hypertable. A hypertable is a partitioned database table that provides an interface of a single continuous table—represented by a virtual view—such that a requestor can query it via a database query language such as SQL. This hypertable may also be known as a parent table, partitioned table, or the like. A hypertable may be defined with a standard schema with attributes (or fields or column) names and types, with at least a time attribute specifying a time value. The hypertable is partitioned along a set of dimension attributes including the time attributes and zero or more other dimension attributes (sometimes referred to as the hypertable&#39;s “space” attributes). These dimension attributes on which the hypertable is partitioned are also referred to as “partitioning key(s)”, “partition key(s)”, or “partitioning fields.” A hypertable may be created using a standard SQL command for creating a database table. Furthermore, queries to the hypertable may be made using database queries, for example, SQL queries. 
     The database system splits the hypertable into chunks. Each chunk stores a subset of records of the hypertable. A chunk may also be referred to herein and elsewhere as a data chunk or a partition, a shard, a child table, or just a table. The database system  110  may distribute chunks of a hypertable across a set of one or more locations. A location may represent a storage medium for storing data or a system that comprises a storage medium for storing data, for example, a server. The storage medium may be a storage device, for example, a disk. The database system  110  may store data on multiple storage devices attached to the same server or on multiple servers, each server attached with one or more storage devices for storing chunks. A storage device may be attached to a remote server, for example, in a cloud-based system and a server of the database system provided access to the remote storage device for storing chunks. 
     The database system can store multiple tables or hypertables, each with different schemas. Chunks within the same hypertable often have the same schema, but may also have different schemas. The database system may also include standard database tables, i.e., traditional non-partitioned tables stored in the same database. Operations are performed against any of these tables, including multiple tables in a single query. For example, this can involve a SELECT that JOINS data between a hypertable and a standard non-partitioned table, or between two hypertables, or any more complex combination thereof. Or, it may involve inserting data into a hypertable and a standard non-partitioned table, or between two hypertables, or more complex combinations, as a single transaction. 
     In some embodiments, the database system  110  is comprised of one or more database system nodes (also referred to as database servers or just servers) that are connected over a network. Each node may include the same or similar components from  FIG. 1 , such as a query processor  130 , metadata store  140 , and data store  145 . The details of a database system node are described in  FIG. 2 . The metadata store  140  stores metadata describing the data stored in the data store  145  including descriptions of various hypertables and standard non-partitioned tables. The description includes various attributes of each table, the description of various chunks of a hypertable, and so on. The query processor  130  receives and processes queries as further described herein. 
     The database system  110  may be connected to requesters issuing database queries to the database system  110 . A requestor may be any source of the database queries, for example, a client device  120 , a webserver, application server, user workstation, or a server or machine that is sending the query on behalf on another origin (e.g., an intermediate server or middleware layer acting as a queue, buffer, or router such as for INSERTS, or an application acting on behalf of another system or user). 
     This connection from the requester often occurs over the network  115 , although it can also be on the same server executing the database system. For example, the network  115  enables communications between the client device  120  or any other requestor and the database system  110 . In one embodiment, the network uses standard communications technologies and/or protocols. The data exchanged over the network can be represented using technologies and/or formats including the open database connectivity (ODBC) format, the Java database connectivity (JDBC) format, the PostgreSQL foreign data wrapper (FDW) format, the PostgreSQL dblink format, the external data representation (XDR) format, the Google Protocol Buffer (protobuf) format, the Apache Avro format, the hypertext markup language (HTML), the extensible markup language (XML), Javascript object notation (JSON), etc. 
     The client device  120  can be a personal computer (PC), a desktop computer, a laptop computer, a notebook, a tablet PC executing an operating system. In another embodiment, the client device  120  can be any device having computer functionality, such as a personal digital assistant (PDA), mobile telephone, smartphone, wearable device, etc. The client device can also be a server or workstation, including running in a backoffice environment, within an enterprise datacenter, or within a virtualized cloud datacenter. The client device executes a client application for interacting with the database system  110 , for example, a browser  125 , a database shell, a web service application (such as .NET, Djagno, Ruby-on-Rails, Hibernate), a message broker (such as Apache Kafka or RabbitMQ), a visualization application, and so forth. 
       FIG. 1  and the other figures use like reference numerals to identify like elements. A letter after a reference numeral, such as “ 120 A,” indicates that the text refers specifically to the element having that particular reference numeral. A reference numeral in the text without a following letter, such as “ 120 ,” refers to any or all of the elements in the figures bearing that reference numeral (e.g. “ 120 ” in the text refers to reference numerals “ 120 A” and/or “ 120 N” in the figures). 
       FIG. 2  illustrates partitioning of data as chunks for a hypertable, in accordance with an embodiment. Each of these chunks correspond to a portion of the entire dataset organized according to some partitioning function involving one or more of a record&#39;s attributes. The attributes of the record that are used for partitioning the hypertable as chunks are referred to as dimension attributes. Accordingly, a chunk corresponds to an “n-dimensional” split of the hypertable (for n≥1). 
     The database system  110  may implement a chunk as a file. In one embodiment, each chunk is implemented using a standard database table that is automatically placed on one of the locations (e.g., storage devices) of one of the database nodes (or replicated between multiple locations or nodes), although this detail may not be observable to users. In other embodiments, the placement of chunks on locations and/or database nodes is specified by commands or policies given by database administrators or users. 
     One of the dimension attributes is a time attribute that stores time-related values. The time attribute can be any data that can be comparable (i.e., has a&gt; and ≥ operator), such that data can be ordered according to this comparison function. Further, new records are typically associated with a higher time attribute, such that this value is commonly increasing for new records. Note that this value can be specified in the data record, and need not (and often does not) correspond to when data is inserted into the database. The following values may be used as a time attribute: datetime timestamps (including with or without timezone information), UNIX timestamps (in seconds, microseconds, nanoseconds, etc.), sequence numbers, and so on. In an embodiment, the hypertable is also split along a dimension attribute that represents a distinct identifier for objects or entities described in the database table (e.g., a device id that identifies devices, a server id that identifies servers, the ticker symbol of a financial security, etc.). 
     A chunk is associated with a set of values corresponding to each dimension attribute. For example, a hypertable may have two dimension attributes d1 and d2. For a given chunk C 1 , the dimension attribute d1 is associated with a set of values S 1  and the dimension attribute d2 is associated with a set of values S 2 . Accordingly, each record stored in the chunk C 1  has a dimension attribute value that maps to a value in the set of values corresponding to the dimension attribute. For example, assume that a hypertable includes attributes time, device, and temperature. Also assume that time is a dimension attribute and a chunk is associated with a range of time [0:00:00-11:59:59.999]. If an input record has values {time: “1:00:00”, device: “A”, temperature: 65}, the chunk may store the input record since the value of the time dimension “1:00:00” falls within the range associated with the chunk, i.e., [0:00:00-11:59:59.999]. 
     A set of values corresponding to a dimension attribute may represent a range of values but is not limited to ranges. For example, the set of values may represent a plurality of ranges that are not contiguous. Alternatively, the set of values may be specified by enumerating one or more values. For example, a dimension attribute c1 may represent colors (e.g., “red”, “blue”, “green”, “yellow”), and a chunk may store records that have the value of dimension attribute c1 from the set {“red”, “blue”} and another chunk may store records that have the value of dimension attribute c1 from the set {“green”, “yellow”}. 
     A given value of a dimension attribute may map to a value in the set of values corresponding to that dimension if the given value is identical to a value in the set of values. Alternatively, a given value v1 of a dimension attribute may map to a value v2 in the set of values corresponding to that dimension if the value v2 is obtained by applying a transformation (for example, a function) to the given value v1. For example, database system  110  may use a hash partitioning strategy where the set of values corresponding to a dimension is specified as a range/set of values obtained by applying a hash function to the dimension attribute values. Accordingly, if a dimension attribute value is represented as vx, and H represents a hash function, a chunk Cx may be associated with a range R=[x1, x2] (or set) of values for H(vx). Accordingly, the chunk may store a record with dimension attribute value v1 if H(v1) lies in the range [x1, x2]. 
     In an embodiment, the set of values may correspond to a plurality of dimension attributes. For example, the hash function specified in the above example may receive two or more inputs, each corresponding to a distinct dimension attribute, i.e., H(v1, v2, . . . ). Accordingly, a dimension of a chunk may be defined as a composite attribute comprising a plurality of dimension attributes of the hypertable. 
       FIG. 2  shows a hypertable  160  split into a plurality of chunks  210  along two dimension attributes, a time attribute and another dimension attribute referred to as the space attribute. In this example, each chunk is associated with a time range comprising a start time and an end time, and a space range comprising a contiguous range of alphabetical characters. For example, chunk  210   a  stores a set of records that have the value of time attribute within the range [0, 6] and the value of space attribute within the range [A, I]. Similarly, chunk  210   b  stores a set of records that have the value of time attribute within the range [0, 6] and the value of space attribute within the range [J, R], and so on. 
     Different types of queries can be made to a hypertable, including those that only read from the hypertable (e.g., database SELECT statements), as well as those that modify the hypertable (e.g., database INSERT, UPDATE, UPSERT, and DELETE statements). Writes are typically sent to the chunks comprised of the latest time interval (but do not need to be), while queries may slice across multiple dimension attributes, for example, both time and space. 
     Although hypertables and chunks are referred to herein as tables, this term is not meant to be limiting, and a chunk could refer to a number of storage representations, including a traditional relational database table, a virtual database view, a materialized database view, a set of structured markup language (e.g., XML), a set of serialized structured data (e.g., JSON, Google Protocol Buffers, Apache Avro, Apache Parquet), or flat files (e.g., with comma- or tab-separated values). 
     The database system also include materialized views, which is data stored in tables derived from other tables in the database system. 
     The following SQL commands show a materialized view MINUTES that is based on a base table RAW in the database system  110 . This materialized view is defined based on some query that is executed against the base table RAW and whose result in stored in a materialization table (the terms materialized view and materialization table may be used interchangeably), although the syntax and format of these commands are just representative. 
     Base Table RAW: 
     
       
         
           
               
               
             
               
                   
                   
               
             
            
               
                   
                 CREATE TABLE raw ( 
               
            
           
           
               
               
            
               
                   
                 time TIMESTAMPTZ NOT NULL, 
               
               
                   
                 device_id TEXT NOT NULL, 
               
               
                   
                 temperature DOUBLE PRECISION NULL, 
               
               
                   
                 humidity DOUBLE PRECISION NULL 
               
            
           
           
               
               
            
               
                   
                 ); 
               
               
                   
                   
               
            
           
         
       
     
     Materialized View MINUTES: 
     
       
         
           
               
               
             
               
                   
                   
               
             
            
               
                   
                 CREATE VIEW minutes AS 
               
            
           
           
               
               
            
               
                   
                 SELECT time_bucket(‘1 minute’, time) as minute, 
               
            
           
           
               
               
            
               
                   
                 device_id, 
               
               
                   
                 min(temperate) as min_temperature, 
               
               
                   
                 avg(temperate) as avg_temperature, 
               
               
                   
                 max(temperate) as max_temperature, 
               
               
                   
                 min(humidity) as min_humidity, 
               
               
                   
                 avg(humidity) as avg_humidity, 
               
               
                   
                 max(humidity) as max_humidity, 
               
            
           
           
               
               
            
               
                   
                 FROM raw 
               
               
                   
                 GROUP BY minute, device_id; 
               
               
                   
                   
               
            
           
         
       
     
     This materialized view is an aggregation over raw data from the base table, where an aggregate typically takes a collection of records (also known as tuples) and produces a single new tuple. Often this new tuple reflects some summary information about the input tuples, such as the min, max, or average of a column of the input tuples. A common aggregation in time-series analysis takes a time-column value and aggregates all tuples corresponding to some time interval (such as a minute) together, as shown above. 
     One of ordinary skill will also recognize that the materialization or aggregation can take many other forms, including approximations or approximate statistics of the raw data, sampling of the raw data, transformations or filtering over the raw data, aggregates that maintain all the information in the raw data but now in some alternative form (that is more amenable to compression or columnar access), and others. 
     When some type of change is performed on a base table, for example, base table RAW (such as an INSERT, UPDATE, or DELETE operation), the database system  110  reflects this change in the materialized view, for example, materialized view MINUTES. To do so, in some embodiments, the database system tracks changes to the portion of the raw data in base table RAW that already have a materialization precomputed in MINUTES, so that the corresponding materialization table can be updated to reflect these changes. In some embodiments this tracking involves recording invalidation information, e.g., to an invalidation log. 
     The database system  110  only track changes on the base table RAW for portions of the data that have had materializations precomputed. In one embodiment, the database system only materializes data for the portion of data that is lagging behind the current time by some time interval (e.g., one hour before the current time). The database system additionally stores information about the maximum timestamp that has already been materialized using a completion threshold (i.e., all data present in the base table before this completion threshold has been materialized in the materialized view). 
     The database system stores additional information related to the base table&#39;s invalidation threshold, which is either equal to the completion threshold or, if the database system is in the process of computing a materialization, more recent than the completion threshold. For ongoing materializations, the invalidation threshold is set to the maximum of either the current invalidation threshold or the maximum timestamp that will be read during the materialization process. That is, the invalidation threshold is set such that it is more recent than any existing or currently-in-process materialization. 
     If any changes (inserts, updates, deletes, or the like) are performed against records in the base table that are more recent that the invalidation threshold (that is, the value of the records&#39; time attribute is greater or newer than the invalidation threshold), then the database engine does not need to record any invalidation information when such changes are performed. If the changed records are older than the invalidation threshold, then the database engine records additional invalidation information, such as in an invalidation log or another data structure in the metadata store. 
     In other embodiments, the database engine stores multiple completion and invalidation thresholds. In such an embodiment, the database engine stores a completion interval defined by completion start and finish thresholds, as well as an invalidation interval defined by its own invalidation start and finish thresholds. In such cases, during a materialization, the invalidation start threshold is set to the minimum of either the current invalidation start threshold or the minimum timestamp that will be read during the materialization, while the invalidation finish threshold is set to the maximum as before. In such cases, the database engine does not record any invalidation information for the changed records that are either older than the invalidation start threshold or newer than the invalidation finish threshold. In other embodiments, the database system can have multiple such completion and invalidation intervals for one base table. In other embodiments, an invalidation interval can be “open” or primarily “one-sided”, such that it records the start threshold and covers the time region from that start threshold to the current time or maximum timestamp among the base table&#39;s records. With such an open invalidation interval, if any new records are added to the base table that are newer than the invalidation interval&#39;s start threshold, the database engine does not need to update the start threshold; while if any new records are added to the base table that are older than the invalidation interval&#39;s start threshold, the database engine updates the start threshold to be less than or equal to the oldest (minimum) timestamp in the new records. In embodiments with partitioned tables, such as hypertables, invalidation information, thresholds, and records (as well as other related information such as completion thresholds, etc.) may be defined on the parent table or hypertable, or on each individual child table or chunk. In some embodiments, invalidation information on each partitioned table or hypertable chunk is stored by marking the chunk as containing invalidated records, such that the entire chunk is recomputed during materialization, rather than a narrower invalidation interval within the chunk. 
     A second materialized view can also be based on a first materialized view, which serves as the base table from the second materialized view&#39;s perspective. Using the example in  FIG. 3 , a second materialized view can be defined as the following, which serves to compute the minimum, average, and maximum values of certain columns of the minutely data. 
     
       
         
           
               
               
             
               
                   
                   
               
             
            
               
                   
                 CREATE VIEW HOURS AS 
               
            
           
           
               
               
            
               
                   
                 SELECT time_bucket(‘1 hour’, minute) as HOUR, 
               
            
           
           
               
               
            
               
                   
                 device_id, 
               
               
                   
                 min(min_temperature) as min_temperature, 
               
               
                   
                 avg(avg_temperature) as avg_temperature, 
               
               
                   
                 max(max_temperature) as max_temperature, 
               
               
                   
                 min(min_humidity) as min_humidity, 
               
               
                   
                 avg(avg_humidity) as avg_humidity, 
               
               
                   
                 max(max_humidity) as max_humidity, 
               
            
           
           
               
               
            
               
                   
                 FROM minutes 
               
               
                   
                 GROUP BY hour, device_id; 
               
               
                   
                   
               
            
           
         
       
     
     When computing one aggregate on another materialized aggregate, the database system can compute them directly as specified, while in other embodiments the database system may store internal data, sometimes referred to as “partials”, differently than as directly specified in the query language. This is often performed so that aggregating the internal data maintains nice transitive properties. For example, to represent the “max” function, the database system can just store the maximum of some set of values, as the max of a set of max values is the same as the max over all raw values. To compute averages, however, the database system may alternatively keep such partials, as the average of a set of averages is not the same as the average over the raw values; in such as case, the database system may internally store the sum and count of the raw values instead, such that it both can compute the average at query time of one set, or aggregate some number of sums and counts to yield a total average over all the raw data. The view definition syntax may provide a way for the user to specify whether they want a materialized view that is based on another materialized view to return an aggregate over the underlying view or the raw data (e.g., an average of averages or an average over the raw data). 
     To maintain its materialized views in such a manner, recall that the database system  110  includes a materialization engine  180 , an invalidation engine  190 , and a query processor  130 , as shown in  FIG. 2 . The materialization engine  180  performs aggregations or other analytical calculations on base tables or materialized views, including in some embodiments joins to other relational or time-series data sources, and stores the results in materialized views. The invalidation engine  190  marks regions of a materialized views as invalidated due to changes made to the view&#39;s underlying base table. The query processor  130  determines how to return results of queries, based on the queries performed, information provided by the invalidation and materialization engines, and optional system configuration. The various database system components, such as the materialization engine  180 , invalidation engine  190 , and query processor, may be located and run on the same physical machines that hold the tables on which they are operating, or the components may be located and run on separate physical machines than the base tables or materialized tables (or partitions thereof) and instead interact with these tables across the network. 
     In some embodiments, materialized views may also be created automatically without explicit user intervention. This automated view creation may occur as a result of certain types of DDL commands, through the use of a design tool in which a user specifies queries to optimize and actions are taken, or through the automatic analysis (including by machine-learning) of query logs, cached queries, or other data or statistics that may enable a system to infer materializations that could speed up queries. 
     Although materialized views, tables, hypertables, and chunks are referred to herein as database tables, this term is not meant to be limiting, and a view, table, or chunk could refer to a number of storage representations, including those belonging to traditional databases (e.g., relational tables, virtual views, materialized views); a set of structured markup language (e.g., XML); a set of serialized structured data (e.g., JSON, Google Protocol Buffers, Apache Avro, Apache Parquet); flat files (e.g., with comma- or tab-separated values); tables or files stored in different storage layouts such as row-major form, column-major form (also known as columnar storage), or other layouts; storage using various types of in-database compression; and other storage representations. 
     Distributed Execution of Queries 
       FIG. 3  shows processing of queries in a database system comprising a plurality of database nodes, in accordance with an embodiment. A database system node  310   a  receives database queries and may send one or more queries to chunks (that may be implemented as physical tables of the data), which are stored on the coordinator database system node or on other database system nodes. A database system node does not issue a query to a chunk if it determines that the chunk is not needed to satisfy the query. This determination uses additional metadata about the chunk, which may be maintained separate from or along with each chunk&#39;s data. Each database system node can also maintain additional metadata to allow it to efficiently determine a chunk&#39;s time interval and partitioning field&#39;s keyspace. The database system may maintain the metadata separate from or along with a chunk. 
     As shown in  FIG. 3 , the database system node  310   a  receives a first database query  320 . The database system node  310   a  determines that the data required for processing the received database query is on one or more database system nodes  310   a ,  310   b , and  310   c . The database system node  310   a  further sends queries  325   a  and  325   b  for processing the first query to the database system nodes  310   b  and  310   c , respectively. All three database system nodes  310   a ,  310   b , and  310   c  process their respective queries using one or more chunks of data stored on their respective nodes. In the example, illustrated in  FIG. 3 , if the database system node  310   a  determines that the data required for processing the first query is stored only on database system nodes  310   a  and  310   b  but not on  310   c , the database system node  310   a  sends a query for processing to  310   b  but not to  310   c . In other embodiments of the system, the queries  325   a  and  325   b  sent to the other nodes  310   b  and  310   c  are the same as the first query  320 , and the queries or requests sent to the other nodes can be in a different query language, format, or communication protocol as the first query. In some embodiments of the system, the queries  325   a  and  325   b  may be identical to each other, while in others they are different. Further, in other embodiments, node  310   a  does not store chunks itself, but only processes the query  320  and issues the corresponding queries  325  to other database nodes. 
     The database system node  310   a  that receives the database query may determine that the query to the hypertable does not involve a particular chunk&#39;s data—for example, because the query specified a time period different than that associated with the chunk, or if the query specifies a dimension attribute (e.g., an IP address, device ID, or some location name) that is associated with a different chunk. In this situation, the first database system node does not issue a query to this particular chunk (which may be located on itself or on a different node). This determination by both the first database system node and any other database system nodes may be performed by the query processor  130  present on each database system node that processes queries. 
     Any database system node may receive a query from a requester and the query processor  130  running on this database system node determines how to plan and execute the query across the entire cluster of one or more nodes. This database system node sends a query (a “subquery”) to zero or more other nodes in the system. Subsequently, the database system node(s) that receive a subquery from the first database system node include a query processor  130  that determines how to plan and execute the query locally. 
     In an embodiment, this process is extended to additional levels of subqueries and involved planners. In an embodiment, the database system performs this partitioning in a recursive fashion. For example, the chunk that is being stored on one of the nodes could itself be further partitioned in time and/or by an additional partitioning key (either the same or different than the partitioning key at a higher level), which itself could be distributed among the node (e.g., on different disks) or even to other nodes. In such a scenario, a chunk can act as another hypertable. 
     In some embodiment, the database system performs the query processing using only the query processor  130  on the first database system node. Accordingly, the complete query plan is generated by the first node and sent to nodes that are determined to store chunks processed by the query. The remaining nodes that receive the query plan (or some portion thereof) simply execute the received query plan without having to generate a portion of the query plan. In other embodiments, the database system implements less homogenous functionality across nodes, such that a first set of one or more nodes receives queries and plans and executes the queries against a second disparate set of one or more nodes that store the chunks. 
     System Architecture 
       FIG. 4A  shows the system architecture of a query processor, in accordance with an embodiment. The query processor  130  comprises components including a connector  410 , a query parser  415 , a query planner  425 , a query optimizer  430 , an execution engine  435 , and a query plan store  455 . A query processor  130  receives a query in some query language, such as SQL, which specifies the tables or datasets on which the query will apply (i.e., read or write data). A query or database query may represent a request to read data (e.g., SELECT statements in SQL) or modify data (e.g., INSERT, UPDATE, and DELETE statements in SQL) from the database. 
     The query parser receives this request and translates it to a query representation that is easier to process. For example, the query parser  415  may generate a data structure representing the query that provides access to the information specified in the query. The query optimizer  430  performs transformation of the query, for example, by rewriting portions of the query to improve the execution of the query. The query planner takes this machine-readable representation of the query, which is typically declarative in nature, and generates a plan specifying how the query should be executed against the stored data, which may be stored in memory (e.g., RAM, PCM) and/or on some type of non-volatile storage media (e.g., flash SSD, HDD). The query processor  130  stores the generated plan in the query plan store  455 . The execution engine  435  executes the query against the stored data, and returns the results to the requester. The connector  410  allows the query processor  130  to connect to remote systems, for example, to access data stored in remote systems. 
       FIG. 4B  shows the system architecture of a chunk management module, in accordance with an embodiment. The chunk management module  170  further comprises a chunk selection module  445 , and a chunk creation module  450 . The chunk selection module  445  implements a chunk selection function that determines a chunk for storing a given record. The chunk selection module  445  determines whether an existing chunk can be used for storing the record. If the chunk selection module  445  determines that none of the existing chunks can be used for storing the record, the chunk selection module  445  determines that a new chunk needs to be created and invokes the chunk creation module  450  for creating the chunk. If the chunk selection module  445  determines that a new chunk needs to be created, the chunk selection module  445  determines various parameters describing the new chunk. For example, the chunk creation module  450  determines the sets of values corresponding to different dimension attributes of the records that define the chunk boundaries. Accordingly, records stored in the chunk have dimension attribute values such that each dimension attribute has a value that maps to a value in the set of values corresponding to the chunk&#39;s dimension. For example, if a chunk has two dimension attributes, based on time and a device id, then each record stored in the chunk has a time attribute that falls within the chunk&#39;s time range and a device id from the set of device ids associated with the chunk. The chunk creation module  450  determines a location for creating the chunk and creates the chunk on the location. 
     The database system  110  stores in the metadata store  140 , metadata  155  describing the chunk. The metadata for a chunk includes information associating the chunk with the hypertable. Other type of metadata describing the chunk includes a name of the chunk, the various sets of values of the dimension attributes (for example, time ranges for the time attribute, and so on), information describing constraints and indexes for the chunk, and so on. The database system  110  may store other metadata associated with the chunk, e.g., access statistics and data distribution statistics to aid query planning. 
     A hypertable may be associated with certain policy configurations, for example, indexes, constraints, storage parameters (e.g., fillfactor settings, parallel worker settings, autovacuum settings, etc.), foreign key relationships, and so on. In an embodiment, each chunk of the hypertable implements the policy configurations of the hypertable containing the chunk. Accordingly, when creating a chunk, the chunk creation module  450  may also create structures such as indexes for the chunk and update metadata to specify constraints, foreign key relationships, and any other policy configurations for the chunk. Examples of constraints defined for a chunk include UNIQUE, NOT NULL, CHECK CONSTRAINT (i.e., timestamp between range), FOREIGN KEY, and EXCLUSION constraints. The chunk management module  170  continues to manage the chunk once it is created, for example, by reindexing old chunks periodically, moving old chunks to slower storage devices over time, adding secondary constraints through dynamic inspection, and so on. 
     In an embodiment, the chunk management module  170  monitors the sizes of the chunks that were recently created. A recently created chunk (or a recent chunk) refers to a chunk that was created within a threshold time interval of the current time. The size of the threshold time interval may be configurable. The size represents the amount of data that is stored in the chunk, for example, the chunk&#39;s size of bytes, its number of rows, and so on. The chunk management module  170  adjusts sets of values of the dimension attributes for new chunks being created based on the size of the recently created chunks. Accordingly, if the chunk management module  170  determines that one or more recently created chunks store data that exceeds certain high threshold values, the chunk management module  170  adjusts the sets of values of one or more dimensions so that they have fewer elements than the corresponding sets of values of the recently created chunks. For example, if the chunk management module  170  determines that the recently created chunks had a range of 12 hours for the time attribute, the chunk management module  170  may decrease the range of time attributes of new chunks being created to be 10 hours. Alternatively, if the chunk management module  170  determines that one or more recently created chunks store data that is below certain low threshold values, the chunk management module  170  adjusts the sets of values of one or more dimensions so that they have more elements than the corresponding sets of values of the recently created chunks that were below the low size thresholds. For example, if the chunk management module  170  determines that the recently created chunks had a range of 12 hours for the time attribute and stored very few records, the chunk management module  170  may increase the range of time attributes of new chunks being created to be 15 hours. 
     In an embodiment, the chunk management module  170  monitors one or more performance metrics for the chunks that were recently created. The chunk management module  170  adjusts the sets of values of dimension attributes for new chunks being created based on the performance metrics for the chunks that were recently created. For example, the chunk management module  170  may monitor insert rate and query execution time. For example, if the chunk management module  170  determines that for the current sizes of chunks the insert rate of records has fallen significantly (e.g., since the database system has started swapping to disk), then the chunk management module  170  determines the sets of values of dimension attributes of new chunks being created such that the new chunks are smaller. 
     In an embodiment, chunk management module  170  keeps statistics describing chunks processed by each distinct query, for example, the number of chunks processed by each query. The chunk management module  170  uses this statistical information to determine sets of values for dimension attributes of new chunks being created so as to improve performance. In an embodiment, the chunk management module  170  monitors the dimension attribute boundaries specified in queries. If the chunk management module  170  determines that commonly received queries have certain pattern of boundaries, for example, a pattern of time alignment (e.g., typical queries request data for a day between midnight and midnight), then the chunk management module  170  aligns newly created chunks to match these boundaries. As another example, if the current chunks have one hour time attribute ranges and the chunk management module  170  determines that the queries are typically accessing data at an interval of a size of a full day, the chunk management module  170  increases the chunk sizes to reach a size more aligned with the access patterns, yet one that still retains a high insert rate. For example, the chunk management module  170  may increase the time attribute range to be 12 hours, e.g., if 12 hours gives a higher insert rate compared to a 24-hour range. 
     In an embodiment, the chunk management module  170  determines the sets of values of the dimension attributes of chunks being created based on ranges of dimension attributes specifies in queries received by the database system. For example, if the chunk management module  170  is creating chunks with time attribute ranges from 11 pm to 11 pm, and the chunk management module  170  determines that the queries received are accessing data from midnight to midnight, the chunk management module  170  shifts the time range of the chunks being created to match the time ranges of the queries. This improves the performance of queries by avoiding the need to unnecessarily scan two chunks rather than one. 
     In an embodiment, the chunk management module  170  distributes chunks across a plurality of locations based on the properties of the storage media of each location. The chunk management module  170  identifies the storage medium for storing the new chunk and accesses properties of the storage medium, for example, properties describing a rate of access of data stored on the storage medium. The chunk management module  170  determines a number of chunks from the plurality of chunks being assigned to a location based on the properties of the storage medium corresponding to that location. For example, the chunk management module  170  accesses metrics describing the rate at which a storage medium accesses random data. Certain storage mediums, e.g., solid-state drives (SSDs) and random-access memory (RAM), can handle random reads much better than spinning hard disk drives (HDDs). Accordingly, the chunk management module  170  assigns more chunks from the plurality of chunks to a location having a storage medium with faster access time for random accesses. 
     In one embodiment, the chunk creation module  450  creates a new chunk—and “closes” an existing one—when the existing chunk approaches or exceeds some threshold size (e.g., in bytes on disk or in memory, in its number of rows, etc.). Each chunk is represented by a start and end time (defining its interval). With a purely size-based approach, however, the database system would not know a priori the end time of a newly-created chunk. Thus, when a chunk is first created, the chunk&#39;s end time is unset; any row having time greater than (or equal to) the start time is associated with the chunk. However, when a chunk&#39;s size approaches or exceeds some threshold, the query planner  425  closes the chunk by specifying its end time, and the chunk creation module  450  creates a new chunk. This new chunk starts at the time the old chunk ends. With this approach, the chunk has an indeterminate end time for a chunk until it is closed. A similar logic is applied to an indeterminate start-time. It is also possible for an initial chunk to have both an indeterminate start and end time. An embodiment of the database system performs this determination and chunk creation asynchronously or in the background, while another performs these actions during the process of inserting a (set of) row(s) from the received batch to the chunk. The creation of the new chunk at insert time can happen in a variety of ways: before inserting the rows (the query planner  425  decides that the existing chunk is too full already, and creates a new chunk to insert into); after inserting the rows into the chunk; or in the middle of inserting the rows (e.g., the query planner  425  decides the chunk only has space for a subset of the rows, so the subset is inserted into the current chunk and the remainder of the set is inserted into a newly created chunk). 
     In other embodiments, the database system defines a chunk as having a particular time interval (that is, both a start and end time) when the chunk is created. Then the system creates a new chunk when needed, e.g., when new data is to be inserted to a time interval that does not yet exist. In one embodiment, the database system also employs a maximum size even with this approach, so that, for example, a second chunk is created with the same time interval as the first chunk if the size is approached or exceeded on the first chunk, and the query planner  425  writes new data to only one of the chunks. Once a second chunk is created, the database system may rebalance data from the first to second chunk. In another embodiment, rather than overlap the time intervals of the first and second chunk, the first chunk&#39;s end time is modified when the second chunk is created so that they remain disjoint and their time intervals can be strictly ordered. In another embodiment, the database system performs such changes asynchronously, so that an over-large chunk is split into a first and second chunk as a “background” task of the system. Further, in another embodiment, this second chunk is created when an insert occurs to a time value that is sufficiently close to the end of a chunk&#39;s time range, rather than only when a record&#39;s dimension attributes (e.g., time) fall outside the dimensions of any existing chunks. In general, many of the variations of the database system&#39;s chunk management may be performed either synchronously at insert time or asynchronously as a background task. Size- and interval-based chunking is further described below. 
     In an embodiment, the chunk creation module  450  performs collision detection to ensure that the new chunks(s) have sets of dimension attributes that are disjoint from existing chunks. For example, assume that the chunk creation module is creating chunks with a time range spanning 24 hours. If the previous chunk stored data with time attribute values until midnight (exclusive) on a date January 1, the chunk creation module  450  next creates chunks with time attribute values from midnight (inclusive) on January 2 to the following midnight (exclusive). As another example, if the chunk creation module  450  is creating chunks with 18-hour intervals of time attribute, if the previously created chunk covered a time interval from midnight to 3 am, the chunk creation module  450  next creates a new 18-hour chunk spanning a time interval from 3 am to 9 pm for the time attribute. The chunk creation module  450  can create multiple chunks having the same time range but having different sets of values for other dimension attributes. 
     The chunk creation module  450  may adjust chunk boundaries based on various criteria, some of which may be conflicting. As an example, consider that the database system has one chunk with a time interval that ends at 3 am, and another chunk from noon to the following midnight. The database system may next receive a request to insert a record having a time attribute value of 4 am. Even if the chunk creation module  450  may be creating chunks with a time range spanning 12 hours, in this scenario, the chunk creation module  450  may create a new chunk spanning only a 9 hour time interval from 3 am to noon in order to enforce disjointness. In some embodiments, the chunk management module  170  determines after a chunk is created that the ranges (or set of values) of the chunk are likely to overlap other chunks created. In these embodiments, the chunk management module  170  modifies the existing ranges of the chunk to ensure that the ranges are disjoint from other chunks. 
     In some embodiments, across different partitions, the database system may align chunk start and end times or maintain them independently. In other words, the system may create and/or close all of a hypertable&#39;s chunks at the same time, or different partitions can be managed distinctly from one another. In other embodiments, there may be special overflow chunks where data that cannot be placed in some existing chunks is placed either temporarily or permanently. 
     The system architecture illustrated in these figures (for example,  FIGS. 1-4 ) are meant to be illustrative; other embodiments may include additional or fewer components, some of these components might not always be present (e.g., a query parser or cache), or these components may be combined or divided in a variety of way (e.g., the query planner, query optimizer, and execution engine). It is understood that such a representation or division would not change the overall structure and function of the database system. For example, one would understand that the methods described herein could be implemented in a system that includes one component performing both query planning and executing, or in a system that includes a separate component for planning, which then passes the plan to an executor engine for execution. 
     The materialization engine  180  determines which regions of the raw data need to be materialized, calculates the result of an aggregate query over these regions of the base table, and writes the result to a materialization table. In a preferred embodiment, the materialization engine  180  is run in a background process on a schedule, but in another embodiment can be run manually through a user-initiated or administrator-initiated command or as part of the logic of another system component. 
     When executing, the materialization engine  180  first figures out what regions of the base table to aggregate. For example, if the last materialization has materialized all data up to 10 minutes ago, then the materialization engine  180  can decide to materialize everything for the last 10 minutes, or it can decide to materialize data from 10-minutes ago to 5-minutes ago, leaving the last 5-minutes yet unmaterialized. The latter approach of leaving the most recent interval unmaterialized is often taken for time-series data since such workloads often heavily modify the recent time period. Often the materialization engine  180  will also read invalidation information (such as invalidation records from the invalidation log) to choose a region to re-materialize in order to update the data in the materialization table with the latest data from the base table. 
     Once the materialization engine  180  decides which regions to materialize, it starts to execute the materialization. To do so, in some embodiments, the materialization engine  180  takes locks on the base table, materialization table, and/or metadata (or records similar information), so that other database processes know that a materialization is ongoing. This approach may be used to protect the system from having two materialization processes run at the same time or from having another process modify the raw table, materialization table, or metadata. 
     Locking is particularly important for invalidation, as any database process that is modifying the base table must know whether to create invalidation records or not. If a database process is modifying a region of the base table that is currently being materialized, that process creates invalidation records for that region. As an optimization, the database process can avoid such invalidation records in the cases in which it knows that the materialization engine  180  will see its modifications. For this optimization to be safe, the system needs to make sure that either the data changes made by the modifying process will be seen by the materialization process or that the modifying process creates an invalidation record. To achieve this, in some embodiments, the materialization engine  180  takes locks to change metadata about which region of data requires invalidation before it reads data from that region. One such approach is described later herein, where the materialization engine  180  needs to move the invalidation threshold higher than or equal to the maximum timestamp that will be read during the materialization process while holding a lock that conflicts with any data-modification process. 
     Once ready to execute (e.g., it holds any necessary locks on the base table), the materialization engine  180  reads the data from base table, perform any calculations needed to generate the materialization based on that data, and write the computed results out to the materialization table. Finally, the materialization engine  180  updates any metadata (e.g., the completion threshold) with information about the state of the materialized data. The materialization engine  180  may also need to delete or overwrite data from the materialization table if it is re-materializing a previously-materialized range. 
     In some embodiments, different aspects of the materialization process may be automated or automatedly tuned according by evaluating usage and usage patterns. For instance, in embodiments in which materializations are calculated in background jobs, the frequency at which jobs are run may be tuned to achieve an ideal balance between resource utilization and materialization lag. As another example, the lag interval may be tuned based on the query and insert workload characteristics. 
     Once an aggregate query has been materialized, any subsequent changes or DML operations on the base table may make the materialized values invalid. The invalidation engine  190  is responsible for tracking information about such DML operations, so as to make it efficient to correct the materialization. Such corrections can then be performed synchronously with the DML operation or asynchronously in a background process. 
     In one embodiment, the information recorded by the invalidation engine  190  during a given DML operation or transaction comprises the minimum value of the time attribute (which we also refer to as the time column) across all records that were modified by that operation or transaction on the base table. In another embodiment, the invalidation engine  190  also records the maximum value of the modified record&#39;s time column. 
     In other embodiments, the invalidation engine  190  may also record which grouped-by values have been affected by a DML operation or use other means to limit the impact of the invalidation to fewer already-materialized rows. 
     In some embodiments, the database system maintains an invalidation threshold such that, for any DML operation where the values of the modified records&#39; time columns are all greater than the invalidation threshold, no invalidation information needs to be recorded. The invalidation threshold is set so that any data above that threshold has not been used in any completed or ongoing materialization and thus need not be invalidated. Setting and moving the threshold are discussed elsewhere herein. 
     In other embodiments, other ranges in the time (or other) attributes of the base table are identified such that modifications to them do not require invalidation. In some embodiments, the invalidation threshold is a range, and the database system tests for containment (or exclusion) within the range to see if the information needs to be recorded. The materialization engine handles moving the thresholds up once materializations have been completed. The materialization engine may take care to interact well with the invalidation engine  190  to maintain transactional guarantees while avoiding pernicious locking behavior. 
     In some embodiments, the invalidation information is recorded by appending to a log. In other embodiments, the invalidation information is recorded by modifying a data structure representing the base table or aggregate query, e.g., by storing one entry for the maximum and minimum value invalidated per base table and the invalidation simply moves the minimum value down (or maximum value up) if it sees a invalidation for a record with a lower time value (or higher time value). In some embodiments, this data structure is a heap, in others a range tree or other data structure optimized for storing ranges. In other embodiments, the invalidation engine  190  marks rows in the materialization table as dirty immediately, or even remove them from the materialization table. 
     In some embodiments, the recording of such minimum and maximum values used for invalidation occurs per DML statement or operation rather than per transaction (which can be a series of operations or statements). 
     Details of processes and steps related to invalidation are further described herein. 
     Inserting Data in a Hypertable 
       FIG. 5  illustrates the process of inserting records into a hypertable stored across a plurality of database system nodes, in accordance with an embodiment. The database system  110  receives  510  an insert query (which we also call an insert request). The insert query identifies a database table, for example, a hypertable, chunk, or a standard non-partitioned database table and specifies one or more records to be inserted into the database table. The database system  110  may store records as a hypertable comprising a plurality of chunks, each chunk stored in a distinct location. 
     Upon receiving  510  the insert query, the query parser  415  parses the insert query. The query planner  425  processes the query, and determines if the query specifies a hypertable, chunk, or a standard non-partitioned database table. If the insert query specifies a standard database table or a chunk, the query planner  425  executes the insert on the specified chunk or the standard database table in conjunction with the execution engine  435  and returns the result(s). 
     If the query specifies a hypertable, the query processor  130  performs the following steps for each record specified in the insert request. The query processor  130  identifies the values of the dimension attributes in the input record. The query processor  130  determines whether the input record should be stored in an existing chunk or in a new chunk that needs to be created. In an embodiment, the query processor  130  determines whether the one or more dimension values of the input record map to values from the set of dimension attribute values of existing chunks storing data of the hypertable; this determination is made to decide whether the record can be stored in an existing chunk. 
     In an embodiment, the query processor  130  provides  520  the dimension attributes as input to a selection function of the chunk selection module  445  that determines whether the record should be stored in an existing chunk or whether a new chunk needs to be created for storing the record. If the selection function finds an existing chunk that matches the record, the selection function outputs information identifying the existing chunk. If the selection function determines that none of the existing chunks can be used to store the record, the selection function outputs a value (for example, a negative number) indicating that a new chunk needs to be created. The chunk creation module  450  determines  540  based on the output of the selection function, if the record matches an existing chunk. If the chunk creation module  450  determines  540  that the record matches an existing chunk, the chunk selection module  445  also identifies the location of the existing chunk, for example, whether the existing chunk is local (i.e., on the current database system node) or remote (i.e., on another database system node). This location can specify a location explicitly or implicitly, including specifying a name of a local database table, the name of a remote database table, the name or network address or a remote server, and so on. Accordingly, the query processor  130  inserts  550  the record in the existing chunk. 
     If the chunk creation module  450  determines  540  based on the output of the selection function that a new chunk needs to be created for storing the record, the chunk creation module  450  determines  560  a configuration of the new chunk comprising sets of values corresponding to different dimension attributes for the new chunk. The chunk creation module  450  may further identify a location for creating the new chunk (including identifying a specific storage device or instead identifying a specific database system node, wherein the identified node in turn identifies a specific storage device attached to it). The chunk creation module  450  creates a new chunk based on the configuration of the new chunk and the identified location. The query processor  130  inserts  580  the record in the new chunk that is created. 
     The chunk selection module  445  may determine that a record cannot be inserted in an existing chunk based on various criteria. A record cannot be inserted in any existing chunk if the dimension attributes of the record do not match the configurations of any existing chunks. In some embodiments, even if the dimension attributes of the record match the configuration of an existing chunk, the chunk selection module  445  may determine that the record cannot be inserted into the chunk based on certain policy considerations. For example, the chunk selection module  445  may determine that the existing chunk is storing more than a threshold amount of data and no new records should be added to the chunk. Accordingly, the chunk selection module  445  determines that the record cannot be added to the existing chunk and the database system cannot insert the record in any existing chunk. 
     To create a chunk locally or to insert the record in a chunk stored locally, i.e., on the current database system node executing the above steps, the database system may perform a function call. To create a chunk remotely or to insert the record in a chunk stored remotely, i.e., on a database system node different from the current database system node, the database system may perform a remote call, for example, a remote procedure call (RPC) or a remote SQL query execution. The instructions executed for creating a chunk or inserting a record into a chunk may also depend on the location of the chunk, for example, the type of storage medium used for storing the chunk. 
     Although  FIG. 5  describes the steps in terms of a selection function, other embodiments can use different functions to compute different values, for example, a first function to determine whether the record should be stored in an existing chunk and a second function to describe a new chunk if the first function determines that the record cannot be stored in any existing chunk. 
     If multiple chunks reside on the same location, rather than using a separate message for each insert query, the query processor  130  may send multiple queries in a single message, or it may also send the multiple records to be inserted in a single query in a single message. If the chunks involved in an insert query reside on multiple nodes, in some embodiment the database system node contacts a query or transaction coordinator for additional information that is used and/or transmitted when subsequently communicating with other database nodes as part of the insert process. 
     In some embodiments, the query processor  130  handles a lack of a timely response or an error in a variety of ways. If a chunk is replicated between multiple nodes, or the record-to-chunk determination process results in more than one chunk, the query processor  130  issues an insert request to one or more of these chunks, discussed further. Finally, the query planner  425  collects any result(s) or status information from the insert queries, and returns some result(s) or status information to the requester. 
     In some embodiments, the database system  110  performs several steps to determine the chunk to which a record belongs, many of which involve using metadata. First, the query planner  425  determines the set of one of more partitions that belong to the hypertable at the time specified by the record (i.e., the value of the record&#39;s time attribute). If this partitioning is static, the query planner  425  uses metadata about the hypertable itself to determine this partitioning. 
     If this partitioning changes over time, the query planner  425  uses the record&#39;s time attribute to determine the set of partitions. In one embodiment, this determination involves first using the row&#39;s time attribute value to determine a particular epoch (time interval), then using this epoch to determine the set of partitions. This partitioning may change in the context of system reconfiguration (or elasticity) as described below. Second, the query planner  425  determines the partition (from amongst this set of one or more partitions) to which the record belongs, using the value(s) of the record&#39;s dimension attribute(s). For each of the dimension attributes used for partitioning in the hypertable, this step may involve applying some function to its value to generate a second value. A variety of functions may be employed for this purpose, including hash functions (e.g., Murmur hashing, Pearson hashing, SHA, MD5, locality-sensitive hashing), the identity function (i.e., simply return the input), a lookup in some range-based data structure, or some other prefixing or calculation on the input. Third, using this second value (the function&#39;s output), the query planner  425  determines to which partition the second value belongs. For example, this step could involve a range lookup (e.g., find the partition [x, y] such that the second value is between x and y, inclusive and/or exclusive), a longest-prefix match on the partition (determine the partition that, when represented by some binary string, has the greatest number of most significant bits that are identical to those of the second value), taking the second value “mod” the number of nodes to determine the matching partition number, or the use of consistent hashing, among other matching algorithms. If the hypertable is partitioned using more than one key, then a function could be applied to more than one input (or functions could be separately applied to multiple inputs), leading to one or more second values (outputs) that would be used to determine the partition to which a record belongs. Finally, each partition for each dimension is associated to a set of chunks (i.e., those chunks which store this partition yet may differ in their time ranges); the query planner  425  then determines a chunk from this set based on the record&#39;s time attribute. 
     Other embodiments implement the step of determining the chunk to which a record belongs in alternate ways. For example, the database system skips the process of first determining a record&#39;s chunk based on its epoch, and instead first determines a set of chunks associated with the record&#39;s time. The query planner  425  computes a function on the record&#39;s partition key(s) to determine the second value(s), and compares this second value against the partition information associated with each chunk in order to select one. These processes can be implemented via a variety of data structures, including hash tables, linked lists, range trees, arrays, trees, tries, etc. 
     There are a variety of other optimized ways to implement the process by which the query planner  425  inserts a batch&#39;s data into chunks, without changing its basic functionality. For example, rather than performing all these steps for every record, the query planner  425  can cache information it determines during its per-record analysis, such as the hypertable&#39;s chunks for a given time or time period. 
     Other embodiments perform the steps for processing a batch in different ways. For example, after determining the first record&#39;s chunk, the query planner  425  scans through the rest of the batch, finding all other records associated with the same chunk (if any exist). The query planner  425  then inserts these records into the selected chunk, and deletes them from the batch. The query planner  425  then repeats this process: selecting a record in the (now smaller) batch, scanning the rest of the batch to find records with a similar chunk association, sending that set of one or more records to the second chunk, and then repeating this process until the batch is empty. 
     The insertion process above describes a record as being associated with a single chunk. Alternatively, a record could map to multiple chunks. For example, the chunking process might create more than one chunk during a particular interval (e.g., if the size of inserted data exceeds some threshold), as described herein, in which case the selection function chooses one, e.g., randomly, round robin, or based on their sizes. As another example, the database chooses to insert the record into multiple chunks to replicate data for reliability or high availability. Such replication can be performed by the query planner  425  as part of the same steps described above, or the query planner  425  first inserts each of the records into a primary chunk, and then the database system  110  replicates the inserted record to the chunk&#39;s replica(s). 
     In an embodiment, the database system  110  replicates the chunks such that different chunks of the same hypertable may be stored with a different number of replicas. Furthermore, the database system may determine the number of replicas for a chunk based on the age of the chunk. For example, recent chunks may be replicated a greater number of times than older chunks. Furthermore, older chunks that have more than a threshold age may not be replicated. The database system  110  may determine the age of a chunk based on the values of the time attribute of the chunk. For example, a chunk that stores records having time attribute within a range [t1, t2] may be determined to be older than a chunk that stores records having time attribute within a range [t3, t4] if the time range [t1, t2] is older than the time range [t3, t4], for example, t2&lt;t3. Alternatively, the age of the chunk may be determined based on the time of creation of the chunk. For example, a chunk created a week ago has an age value that is greater than a chunk created today. 
     In an embodiment, the database system replicates different chunks to locations having different characteristics. The database system selects a location having particular characteristics based on the configuration of the chunk. For example, the database system stores and/or replicates recent chunks which are regularly being accessed (for inserts or selects) on fast storage media (e.g., SSDs), while the database system stores and/or replicates old chunks on slower storage media (e.g., HDDs). 
     In an embodiment, the database system reuses replication techniques that apply to the database&#39;s underlying tables, namely, physical replication of the entire database and cold/hot standbys, logical replication of individual tables, as well as backups. It also uses the database&#39;s write-ahead log (WAL) for consistent checkpointing. In other words, even though replication or backup policies are defined (or commands issued) on the hypertable, the system performs these actions by replicating or checkpointing the hypertable&#39;s constituent chunks. In another embodiment, replication and high availability is implemented directly by the database system by replicating writes to multiple chunk replicas (e.g., via a two-phase commit protocol), rather than by using the database&#39;s underlying log-based techniques. 
     In an embodiment, the database system allows different policies to be defined based on chunk boundaries, e.g., a higher replication level for recent chunks, or a lower replication level on older chunks in order to save disk space. 
     In an embodiment, the database system also moves chunks between locations when they age (e.g., from being stored on faster SSDs to slower HDDs, or from faster or larger servers to slower or smaller servers). The database system associates each hypertable with a threshold age value. The database system further associates locations with types. For example, different types of locations may have different access time, different storage capacity, different cost, and so on. If the database system identifies a chunk of the hypertable having an age value greater than the threshold age value of the hypertable, the database system moves the identified chunk from a location having a particular type to another location having a different type. As a result, the database system may store different chunks of the same hypertable in different types of location. Furthermore, the database system automatically changes the mapping of the chunks of the hypertable to locations over time as newer chunks are received and existing chunks get older. In another embodiment, this movement only happens when requested by a command (e.g., from an external process or database user), which specifies the age associated with the hypertable and the locations between which to move any selected chunks. 
     Processing Queries Reading Data 
       FIG. 6  is a flowchart of the process of executing a query for processing records stored in a hypertable, in accordance with an embodiment. The database system receives  610  a query for reading data (e.g., via a SELECT statement in SQL). Upon receiving a query, the query parser  415  parses the query (optionally using a cache of parsed queries). The query planner  425  processes the query and determines if any table specified in the query corresponds to a hypertable, chunk, or a standard non-partitioned database table. The database system performs the following steps in these different scenarios, each resulting in some result being returned to the requester (or some form of error if any problems occur). 
     For every hypertable specified in the first query, the query planner, in conjunction with the execution engine  435 , performs the following steps. First, the query planner  425  analyzes the query to determine  620  the set of chunks that may contribute results to the query&#39;s answer. This analysis typically involves the constraints specified by the query&#39;s predicates as well as metadata that the database system  110  maintains about chunks. For example, these constraints may be based on the value of a particular field (e.g., selected rows must have a device identifier that equals either  100  or  450 ), or they may include some type of time range (e.g., selected rows must specify that their time value is within the past hour, or between July 2016 and August 2016). Metadata stored about each chunk may specify, among other things, the range of time and any other partitioning key(s) associated with a particular chunk. For example, a chunk might be storing the last day of data for device identifiers between 0 and 200. These examples are simply illustrative and a variety of techniques that the system may employ are described herein. The query planner  425  uses the metadata to determine the appropriate chunks, e.g., a device identifier of 100 will be associated with the chunk storing device identifiers between 0 and 200. 
     The following steps  630 ,  640 ,  650 , and  660  are repeated for each chunk determined. The query planner  425  uses metadata to determine the location(s)—e.g., storage devices such as local or network-attached disk(s), or other database system node(s)—at which these chunk(s) are being stored. These chunks may be stored on a location local or remote to the query planner  435 . The query planner  425  determines  640  whether the chunk is stored locally or on a remote server. If the query planner  425  determines that the chunk is stored in a local location, the query planner  425  queries the local chunk (e.g., via direct function calls) or else the query planner  425  sends  660  a query to the remote location storing the chunk (e.g., by issuing SQL queries such as via foreign data wrappers, by sending remote procedure calls (RPCs), etc.). Furthermore, the query planner  425  may change the query execution or plan depending on the properties of the location that stores them (e.g., type of disk or node). When multiple chunks share the same location, the query planner  425  can generate a single query for the location&#39;s set of chunks or a separate query per chunk, and these separate queries can be sent in a single message to the location or as a separate message per query. 
     The query planner  425  issues queries to these locations and waits for their results. If some locations are not responding after some time or return errors, the query planner  425  can take several different options, including retrying a query to the same location, retrying a query to a different location that replicates the chunk, waiting indefinitely, returning a partial result to the client, or returning an error. The query planner  425  receives  670  or collects the results of these queries and merges the results. Depending on the query, the results, metadata, and additional information, the query planner  425  optionally may determine that it needs to query additional chunks to resolve the first query (e.g., when “walking back in time” from the latest time interval to older intervals in order to find some number of values matching a particular predicate). 
     Depending on the query, the query planner  425  may perform  680  post-processing of the results. Such post-processing includes taking a union over the returned results, performing an aggregation like a SUM or COUNT over the results, sorting the merged results by a specific field, taking a LIMIT that causes the system to only return some number of results, and so on. It may also involve more complex operations in merging the chunks&#39; results, e.g., when computing top-k calculations across the partial results from each chunk. Finally, the system returns the result(s) of this first query. The result of the query may comprise one or more tuples or an error code if the processing of the query resulted in an error. 
     In some embodiment, a query across multiple database nodes may also involve the use of a query or transaction coordinator, such that the coordination is contacted for additional information that is used and/or transmitted when subsequently communicating with other database nodes as part of the query process. 
     A node may also receive a query to a chunk or chunks, e.g., because it is the recipient of a query generated by the processing of the first query to a hypertable. For every chunk specified in the query, the query planner  425  performs the following steps. The query planner  425  plans and executes the query on the local chunk. This uses query planning techniques including choosing and optimizing the use of indexes, performing heap scans, and so forth. The query planner  425  receives the results of the query. Third, depending on the query, the query planner  425  may also post-process the results (e.g., sorting the data, performing an aggregation, taking the LIMIT, etc. as described above). It then returns the query&#39;s result(s). 
     A database system node may receive a query to a traditional database table, which involves processing the query in a standard way: planning and executing the query on the specified table, receiving the results, post-processing the results optionally, and returning the result(s). 
     The query may also specify multiple tables or joins between tables. The database system&#39;s processing depends on the types of tables specified (e.g., hypertables, chunks, standard non-partitioned tables) and is related to the steps above, although individual steps may differ or additional steps may be required based on the actual query. 
     Alternative Embodiments for Processing Queries Based on Hypertables 
     Ideally database users should be able to interact with time-series data as if it were in a simple continuous database table. However, for reasons discussed above, using a single table does not scale. Yet requiring users to manually partition their data exposes a host of complexities, e.g., forcing users to constantly specify which partitions to query, how to compute JOINs between them, or how to properly size these tables as workloads change. 
     To avoid this management complexity while still scaling and supporting efficient queries, the database system hides its automated data partitioning and query optimizations behind its hypertable abstraction. Creating a hypertable and its corresponding schema is performed using simple SQL commands, and this hypertable is accessed as if it were a single table using standard SQL commands. Further, just like a normal database table, this schema can be altered via standard SQL commands; transparently to the user, the database system atomically modifies the schemas of all the underlying chunks that comprise a hypertable. 
     In an embodiment, the database system provides this functionality by hooking into the query planner of a relational database like PostgreSQL, so that it receives the native SQL parse tree. It uses this tree to determine which servers and hypertable chunks (native database tables) to access, how to perform distributed and parallel optimizations, etc. 
     Many of these same optimizations even apply to single-node deployments, where automatically splitting hypertables into chunks and related query optimizations still provides a number of performance benefits. This is especially true if the chunks are distributed across the various locations of a node (e.g., across multiple local or network-attached disks). In an embodiment, the placement of chunks on database nodes is specified by commands or policies given by database administrators or users. 
     In an embodiment, the database system partitions its hypertable in only a single dimension—by time—rather than two or more dimensions (for example, time and space dimensions). For example, partitioning based on a single time dimension may be used for deployments of the database system on a single node rather than a cluster of nodes. 
     Additionally, hypertables can be defined recursively. In particular, a hypertable&#39;s chunk can be further partitioned (by the same or different partitioning key, and with the same or different time intervals) and thus act like another hypertable. 
     Chunks are dynamically created by the runtime and sized to optimize performance in both cluster and single-node environments. Partitioning a hypertable along additional dimension attributes (in addition to time) parallelizes inserts to recent time intervals. Similarly, query patterns often slice across time or space, so also result in performance improvements through chunk placements disclosed herein. 
     The placement of these chunks can also vary based on deployment, workload, or query needs. For example, chunks can be randomly or purposefully spread across locations to provide load balancing. Alternatively, chunks belonging to the same region of the partitioning field&#39;s keyspace (for example, a range of values or hashed values, or a set of consecutive values of the key), yet varying by time intervals, could be collocated on the same servers. This avoids queries touching all servers when performing queries for a single object in space (e.g., a particular device), which could help reduce tail latency under higher query loads and enable efficient joins. 
     The database system determines where a chunk should be placed when it is created; this determination is based on a variety of one or more metrics, including performed randomly or via a round-robin distribution strategy, based on server load (e.g., request rate, CPU utilization, etc.), based on existing usage (e.g., size of existing chunks in bytes or number of rows), based on capacity (e.g., total memory or storage capacity, free memory, available storage, number of disks, etc.), based on configured policy or specified by an administrator, and so forth. The database system or administrator may also choose to relocate (move) or replicate chunks between servers. 
     Even in single-node settings, chunking still improves performance over the vanilla use of a single database table for both read and write queries. Right-sized chunks ensure that most or all of a table&#39;s indexes (e.g., B-trees) can reside in memory during inserts to avoid thrashing while modifying arbitrary locations in those indexes. Further, by avoiding overly large chunks, the database system avoids expensive “vacuuming” operations when removing data, as the system can perform such operations by simply dropping chunks (internal tables and/or files), rather than deleting individual rows. For example, this removal may be the result of data deletions (e.g., based on automated data retention policies and procedures), or it may be the result of a large batch insert that fails or is interrupted (which the non-committed rows needing to subsequently be removed). At the same time, avoiding too-small chunks improves query performance by not needing to read additional tables and indexes from disk, or to perform query planning over a larger number of chunks. 
     The database system considers a few factors for determining a chunk&#39;s size. First, the database system maintains metadata that specify the number of partitions into which an additional partitioning field splits a particular time interval. For example, 10 machines each with 2 disks might use 20 partitions (or multiple partitions per server and/or disk). This implies that the keyspace of a particular field (e.g., a device ID, IP address, or location name) is divided into 20 ranges or sets. The database system then determines to which range (or partition) a particular value is associated by performing a lookup or comparison process. In one embodiment, the field is a string or binary value, and the database system splits the keyspace by prefix of the values of the field, then maps a value to one of these partitions based on the partition that shares the longest common prefix. Alternatively, the database system uses certain forms of hashing, such that the hash output&#39;s space is divided again into a particular number of ranges or sets (e.g., contiguous ranges, sets defined by splitting the entire hash output space, sets defined by taking the hash output space “mod” the number of nodes, sets defined by consistent hashing, etc.). The database system applies a hash function to the input value to yield an output value; the database system determines the range or set that includes the output value, which then corresponds to the partition to which the input value belongs. The database system may use a variety of functions in such a context, including hash functions (e.g., Murmur hashing, Pearson hashing, SHA, MD5, locality-sensitive hashing), the identity function (i.e., simply return the input), or some other prefixing or calculation on the input. 
     Second, once the number of partitions based on partitioning keys is determined—and in fact, this number can change over time due to elasticity, discussed below—then the time-duration of the chunk also determines its size. For a constant input rate and some given number of partitions, a chunk with a hour-long time interval will typically be much smaller than one with a day-long interval. 
     In one embodiment, the database system makes the time intervals static or manually configurable. Such an approach is appropriate if the data volumes to the system are relatively stable (and known), and this provides the database administrator or user with control over the database system&#39;s operation. But, such fixed time intervals may not work as well as data volumes change—e.g., a time interval appropriate for a service pulling data from 100 devices is not appropriate when that system scales to 100,000 devices—or require care that the administrator or user change interval sizes over time (either to apply to future intervals or to split existing intervals into multiple chunks). 
     In one embodiment, the database system determines chunks&#39; time intervals dynamically based on chunk sizes, rather than based on a fixed time interval. In particular, during insert time, the database system determines if a chunk is approaching or has exceeded some threshold size, at which time it “closes” the current chunk and creates a new chunk (e.g., by using the current time as the ending time of the current chunk and as the starting time of the new chunk). 
     This threshold size is given a default in software configuration, this default can be configured by the database system administrator, and this size can be changed by the administrator or the database system&#39;s logic during runtime (so that chunks in the same database system can have different threshold sizes). In an embodiment, the database system chooses the size as a function of the system&#39;s resources, e.g., based on the memory capacity of the server(s), which may also take into account the table schema to determine the amount of indexing that would be needed and its size requirements. This tuning takes into account realized or potential changes in the schema over time. For example, if indexes are added to many fields (columns), the amount of memory needed to store these fields changes, which leads the database system to use smaller chunks; if many fields are not indexed, the database system may account for these differently than a schema without any unindexed fields (as indexes may later be added to these fields to enable more efficient queries). Alternatively, recognizing that the database ultimately stores tables in files in the underlying file system that have a maximum size (e.g., 1 GB), the system ensures that the chunk size is smaller than this maximum size. In an embodiment, the size is chosen as a measured or estimated result of read/write performance on the chunk size. 
     In some embodiments, the database system creates a new chunk even when the current chunk size is less than some threshold (i.e., it is “approaching” the threshold, and has not yet exceeded or equaled it), in order to leave some “free space” for the possibility of out-of-time-order data that the database system must backfill into an older chunk. When writing to an older or “closed” chunk, different embodiments of the database system allow the chunk to grow arbitrarily large, create a new overlapping chunk just for the newly written excess data, or split the existing chunk into two, among other approaches. If overlapping chunks are created, the database system follows its policies for writing and reading to overlapping chunks. 
     In another embodiment, the database system determines a chunks&#39; time intervals dynamically based on historical intervals and their sizes. In this case, new chunks are created with an end time, but that end time is automatically set by the database system based on the resulting size of earlier chunks that had a certain interval duration. For example, if the database system (or user or administrator) desires chunks of size approximation 1 GB, and the previous 12 hour chunk resulted in a chunk of size 1.5 GB, then the database might create a subsequent chunk of size 6 hours. The database system can continue to adapt the intervals of chunks during its operation, e.g., to account for changing data volumes per interval, to account for different target sizes, etc. 
     In some embodiments, the database determines chunks based on a hybrid of time intervals and threshold sizes. For example, the database system (or administrator) specifies that a chunk have a pre-determined time interval—so that, as described above, the start and end time of a chunk are specified at creation time—but also that a chunk also have a maximum size in case the insert rate for that interval exceeds some amount. This approach avoids a problem with chunking based purely on fixed time-intervals in scenarios where system load per interval changes over time. If the chunk&#39;s size approaches or exceeds its maximum permitted threshold during the middle of the current time interval, the database system creates a new chunk that overlaps the same interval, or the database system switches to the use of a different time interval. For the former, both chunks represent the same interval, so inserts could choose to write to one of them (while reads query both of them). For the latter, the database system may change a chunk&#39;s time interval to something smaller, and create a new non-overlapping chunk to succeed it in time. As described earlier, such chunk management may be performed synchronously or asynchronously, e.g., a background task splits an over-large chunk into two chunks. 
     Such chunking may also limit the pre-determined time intervals to regular boundaries (e.g., 1 hour, 6 hours, 12 hours, 24 hours, 7 days, 14 days), rather than arbitrary ones (e.g., 11 minutes, 57 minutes). This embodiment causes chunk intervals to align well with periods of time on which data might be queried or deletions might be made, e.g., according to a data retention policy such as “delete data more than 12 hours old”. That way, the database system implements such policies by dropping entire chunks once their records are all at least 12 hours old, rather than partially deleting individual rows within chunks: dropping entire chunks (database tables) is much more efficient than deleting an equivalent number of rows within a table. 
     The database system selects these boundaries in a manner that the boundaries compose well, e.g., they are multiples of one another or are aligned in some other ways. The switching between various interval sizes is performed automatically by the database runtime (e.g., in response to changing data rates) or through configuration by a user or administrator. Similarly, rather than always closing a chunk and creating a new one based on an automated policy, an administrator may signal the database system to create a new chunk or chunk interval via a configuration command. 
     In one embodiment, the database system also applies such adaptation of the chunk&#39;s configuration to non-time dimension attributes that are used to define a chunk&#39;s ranges. For example, if a hypertable&#39;s partitioning is also performed on a field representing a device id, the database system can increase the number of partitions (sets of values) defined on this field from 10 to 20. Such a change, which may be performed automatically by the database system or through configuration by a user or administrator, can be used to increase hypertable performance. For example, if queries typically specify a single device id from which to SELECT data, the query&#39;s latency can be improved if the chunks that contain the specified device include information about a fewer other devices, which can be made to occur by increase the number of partitions over the device id field. 
     In another embodiment, the database system can employ different time intervals across different partitions. For example, if a hypertable&#39;s partitioning is also performed on a field representing a customer id (e.g., where each distinct customer id is a separate partition), then the database system may independently maintain different time intervals (when partitioning on the time attribute) for different customer ids. Such an approach can be beneficial if different customers have very different insert and select query patterns, as well as different data retention needs. 
     In general, the database system employs a variety of methods for chunk management, given that there are multiple different goals and engineering trade-offs between approaches. These goals include optimizing sizes, aligning time intervals for dropping chunks while retaining data integrity, minimizing locking or other performance penalties due to mutability, avoiding arbitrary-sized intervals, creating chunk boundaries that are most advantageous for constraint exclusion, increasing system parallelism, improving query performance, and simplifying code, operation, and management complexity, among others. Different deployments of the database system may choose to use different approaches based on their setting and needs. 
     Adjusting Partitioning Policies in View of System Reconfiguration 
     The amount of data stored in a database systems  110  increases over time. For example, large amount of time series data may be received by a database system  110  and stored in database tables. Database systems  110  often reconfigure the system to increase the storage capacity, for example, by adding storage devices. Conventional systems adapt to the change in the system configuration by moving data. For example, a system may get reconfigured as a result of addition of new servers and may move some chunks of data from existing servers to the new servers, in order to ensure that the new servers are bringing additional capacity to the system. As a result, a large amount of data is moved, thereby making the system reconfiguration an expensive and time-consuming process. This new configuration of participating servers is also referred to as a “view” which represents the set of servers and their configuration, such as the servers&#39; capacity or number of disks. The ability of a system to adapt to changes in computing resources so as to be able to effectively use all available resources if referred to as elasticity. 
     Embodiments of the database system  110  adapt to reconfiguration of the system without performing such data movement. In particular, the database system  110  provides elasticity by creating a new set of chunks and partitioning when the database system is reconfigured for increasing the storage capacity. The database system may use a different partitioning policy for the new set of chunks that are created after the system is reconfigured. For example, if the previous partitioning policy created 20 partitions for 10 servers, the new partitioning policy might create 30 partitions to take into account 5 new servers that are added to the database system. In another example, the previous partitioning policy may create 20 partitions to place 5 partitions on each of 4 servers, but when an additional 1 server is added, the new partitioning policy may then place 4 partitions on each of the 5 servers. In some embodiments, the database system distributes a plurality of chunks created such that new servers are assigned more chunks from the plurality of chunks than existing servers. This allows better balancing of load across the servers. In another embodiment, new servers are assigned larger chunks compared to chunks assigned to existing servers. Larger chunks have configuration that allows them to potentially store more data than smaller chunks. Data can still be read or written to previously created chunks or the newly created chunks. Because writes to time-series datasets are typically made to the latest time interval, and many query workloads also process recent data, load balancing across the new set of servers is still maintained, even without moving the existing data. 
       FIGS. 7 (A-B) illustrate partitioning of data of a database table to adapt to the addition of locations to the database system according to an embodiment of the invention. 
     As illustrated in  FIG. 7(A) , the database system  110  can have a plurality of storage locations  710   a ,  710   b ,  710   c , and  710   d .  FIG. 7  illustrates the distribution of data of a database table with attributes comprising a time attribute and a space attribute (recall that we use the term “space” partitioning to signify any partitioning over a non-time attribute). In response to requests to insert records in the database table, the database system  110  distributes data of the database table according to a partitioning policy that assigns chunks  210  to locations  710 . In the example, configuration shown in  FIG. 7(A) , the database system  110  creates a plurality of chunks including  210   a ,  210   b ,  210   c , and  210   d  and assigns one chunk to each location. The chunks are distributed across the locations of the database system  110  along the time and space attributes. Accordingly, each chunk is associated with a time range and a space range and stores records that have time and space attributes that lie within the time and space ranges of the chunk. In the example configuration shown in  FIG. 7 , each of the chunks  210   a ,  210   b ,  210   c , and  210   d  is associated with the same range of time attribute, i.e., [0, 6] but has a different range of the space attribute. For example, chunk  210   a  has space range [A, F], the chunk  210   b  has space range [G, L], the chunk  210   c  has space range [M, S], and the chunk  210   d  has space range [T, Z]. 
       FIG. 7(B)  shows the partitioning of the chunks of the database table after some time has passed, such that the database system has received requests to insert records with a time attribute later than 6. In response to receiving requests to insert records with a time attribute of 7, for example, the database system creates a new plurality of chunks,  201   e ,  210   f ,  210   g , and  210   h . The new plurality of chunks are distributed across the locations according to the same partitioning policy as above. According to this partitioning policy, each chunk from the new plurality of chunks is associated with a new time range [7, 15]. In this illustration, the chunks stored in the same location have the same space range. For example, both chunks  210   a  and  210   e  assigned to location  710   a  have the space range [A, F], both chunks  210   b  and  210   f  assigned to location  710   b  have the space range [G, L], and so on. The database system could also assign chunks with different time intervals but the same space range to different locations. 
       FIG. 7(C)  shows the partitioning of the chunks of the database table after a new location  710   e  is added to the database system  110 . As a result, the database system  110  has a plurality of locations that include locations  710   a ,  710   b ,  710   c ,  710   d , and  710   e . Although  FIG. 7  shows a single location being added to the database system, more than one locations may be added to increase the storage capacity of the database system  110 . In response to addition of the new location, the database system  110  uses a new partitioning policy to distribute records across the locations. Accordingly, in response to receiving subsequent insert requests, e.g., with values for dimension attributes that do not map to any of the existing chunks, the database system  110  creates a plurality of chunks including  210   i ,  210   j ,  210   k ,  210   l ,  210   m , and  210   n . The chunks  210   i ,  210   j ,  210   k ,  210   l  are mapped to the locations  710   a ,  710   b ,  710   c ,  710   d , and chunks  210   m  and  210   n  are both mapped to the new location  710   e . In other embodiments, the database system may assign more or fewer chunks to the new locations that are added. Accordingly, subsequent records received are distributed according to the new partitioning policy. In the embodiment illustrated in  FIG. 7 , the database system  110  does not move any data that was stored in the chunks that were created before the new locations were added. However, the chunks that are created responsive to the addition of the new locations are distributed according to a new partitioning policy that balances storage of data across all available locations. In the example, shown in  FIG. 7(C) , more chunks are assigned to the new location(s) since the storage and computing resources of the new locations are likely to be underutilized compared to the existing locations that have previously stored data. However, over time, as additional data gets stored on the new locations, the utilization gap between the new locations and existing locations reduces without having to move any data from the existing locations to the new locations. 
     As illustrated in  FIG. 7(C) , the new partitioning policy creates a plurality of chunks that has more chunks after new locations are added. Accordingly, each space range is smaller in the new partitioning policy compared to the space ranges of the portioning policy used before addition of the new locations. 
     In another embodiment, the database system assigns a larger fraction of new data to the new locations not by assigning a larger number of chunks to those locations, as shown in  FIG. 7(C) , but by assigning chunks with dimension ranges that have a larger set of values. For example, rather than having chunk  210   m  with the space range [Q, U] and chunk  210   n  with the space range [V, Z], the database system could create a single chunk assigned to location  710   e  with a space range [Q, Z]. 
     In some embodiments, when the database system  110  detects that new locations are being added to the database system, the database system  110  dynamically changes the partitioning based on the new storage configuration. In other embodiments, the partitioning policy is configured by a user, for example, a database system administrator. 
     A partitioning policy determines how new chunks are created and assigned to locations for storing them. For example, if a partitioning policy is being enforced and new chunks need to be created (for example, to insert records than cannot be inserted in existing chunks), a plurality of chunks may be created and distributed according to the partitioning policy. The partitioning policy may specify various aspects of creation of new chunks including the number of chunks being created, the configurations of individual chunks being created (the configuration comprising the sets of values of different dimension attributes for each chunk), and the mapping of the chunks to locations. 
     The partitioning policy may store information specifying various aspects of the chunk creation/distribution as metadata, for example, the mapping from chunks to locations may be stored using a mapping table that explicitly stores locations for each chunk being created. Alternatively, the partitioning policy may specify various aspects of chunk creation/distribution using instructions, for example, the partitioning policy may specify mapping from chunks to locations using a function (or a set of instructions) that determines a location for a chunk given the chunk configuration and potentially other system information as input. Different partitioning policies may specify different mapping functions (or sets of instructions). Alternatively, different partitioning policies may use the same mapping function (or sets of instructions) but pass different parameter values as input. Such mapping functions (or sets of instructions) may include random selection, round-robin selection, hash-based selection, selection based on the number, size, or age of chunks being stored, selection based on the age of when the location was added to the database system, load balancing strategies based on server resources (including insert or query rates, CPU capacity, CPU utilization, memory capacity, free memory, etc.), load balancing strategies based on disk resources (including total disk capacity, unused disk space disk, disk TOPS capacity, disk TOPS use, etc.), and other criteria or algorithmic approaches, as well as some combination thereof. A partitioning policy may use a combination of the above techniques. 
     In an embodiment, a partitioning policy specifies the size of the plurality of chunks being created. The size of the plurality of chunks may represent the number of chunks in the plurality of chunks being created. Alternatively, the size of the plurality of chunks may represent the aggregate size of chunks in the plurality of chunks being created, where the size of each chunk represents a measure of the amount of data that can potentially be stored in the chunk. The size of a chunk is determined based on the configuration of the chunk comprising the sets of values of the different dimension attributes for records stored in the chunk. For example, the database system may create larger or smaller chunks by specifying larger/smaller ranges (or sets of values) for dimension attributes respectively. 
     In some embodiments, the database system  110  moves existing data under certain scenarios. For example, the database system may enforce a policy that aligns chunks to specific time intervals. Accordingly, the creation of new chunks at a time based on the time that new locations are added may result in violation of such policy. For example, the database system may enforce a standard that chunks have a time range of 12 hours. However, if the addition of new locations to the database system occurs at 3 hours into a 12-hour time interval, the database system would either not be able to incorporate the new locations for another 9 hours, or would have to maintain some chunks with 3 hours intervals. Thus, in certain scenarios, for example, if the amount of data stored in each chunk that is currently being populated is below a threshold amount, the database system moves or reallocates existing chunks rather than create new ones responsive to addition of new location. Accordingly, the database system moves data of the set of chunks being currently populated with records across a new set of chunks distributed across the new plurality of locations and continues adding records to the new set of chunks. 
     In another embodiment, the database system delays enforcement of the new partitioning policy based on the new locations added until the time matches well with chunk alignments. This delayed action can be used both when adding new servers, removing servers in a planned manner, or even on server crashes (if the system already replicates chunks between multiple servers for high availability). For example, if the system already has chunks with time ranges that extend until midnight, and the reconfiguration time is at 11 pm, the database system may not create chunks based on the new partitioning policy for 1 hour (e.g., until a record is inserted with a time attribute after midnight), but the reconfiguration will have an effect when a new set of chunks is created. In such a scenario, the existing chunks are not reconfigured and only the new chunks are allocated over the new set of servers. However, the time range of the chunks is the same before and after the addition of the new locations. 
       FIG. 8  shows a flowchart illustrating the process of modifying a data partitioning policy of a database system in response to the addition of new locations to the database system, in accordance with an embodiment. The database system  110  includes a plurality of locations, referred to as the first plurality of locations. The database system  110  receives  810  requests to insert records in a hypertable. The database system distributes the chunks in accordance with a first partitioning policy P 1 . Accordingly, the database system  110  creates  820  a plurality of chunks and distributes them across the first plurality of locations. For example, if the database system has 5 locations, the database system  110  may create 20 chunks and store 4 chunks in each location. The database system  110  distributes the chunks based on dimension attributes of the records including at least a time attribute. The partitioning policy specifies various aspects of chunk/creation and distribution including the number of chunks that may be created, the configuration of the chunks, and the mapping of the chunks to locations. The database system may repeat the steps  810  and  820  multiple times, for example, until the database system  110  is reconfigured to change the number of locations. 
     The database system  110  receives an indication of the addition of one or more new locations. For example, a new location may be a storage device that is added by a system administrator to an existing server of the database system. Alternatively, a new location may be a new server comprising one or more storage devices that is added to the database system for storing as well as processing data. As another example, a location may be storage device of a remote system on which the database system  110  is allowed to store data, for example, a cloud-based storage device. The indication of the addition of one or more new locations that the database system receives may identify a specific storage device that is added to the database system or may identify a server that is added to the database system. 
     In an embodiment, the database system  110  receives the indication of addition of a location by performing a check of all peripheral devices and servers that can be reached by one or more database system nodes  310 . In other embodiments, the database system  110  receives the indication by receiving a message from a new location, by a command executed by a database user or administrator. The addition of the locations to the database system causes the database system  110  to have a second plurality of locations that is more than the number of locations in the first plurality of locations. The indication of addition of the one or more locations is associated with a reconfiguration time, for example, the time that the indication is received or the time when the addition of the one or more new locations was completed. 
     Subsequent to receiving the indication of the addition of one or more new locations, the database system receives insert requests. The database system  110  creates  840  a second plurality of chunks, for example, if the records in the insert requests received cannot be inserted in existing chunks. The database system  110  creates the second plurality of chunks and assigns them to locations based on a second partitioning policy P 2 . The second partitioning policy P 2  maps the second plurality of chunks to the second plurality of locations, for example, as illustrated in  FIG. 7(C) . The chunks may be uniformly distributed across the second plurality of locations. Alternatively, the number or partition ranges of chunks assigned to the new locations may be greater than the number or partition ranges of chunks assigned to the existing locations. For example, more chunks from the second plurality of chunks may be assigned to the new locations compared to the existing locations. Alternatively, chunks configured to store more data may be assigned to new locations compared to the existing locations. A chunk C 1  may be configured to store more data compared to a chunk C 2  by specifying for chunk C 1 , a set of values for a dimension attribute that has more elements compared to the set of values for the same dimension attribute for chunk C 2 . For example, the time attribute for chunk C 1  may be specified to have a larger time range compared to the time attribute for chunk C 2 . 
     The database system  110  subsequently receives  850  requests to insert data in the database table. The database system  110  stores  860  the received records into chunks based on the dimension attributes of the records. The records may be inserted in chunks created either based on the first partitioning policy or the second partitioning policy as further described herein in connection with  FIGS. 9-12 . The database system  110  identifies a reconfiguration time T associated with the addition of the new locations to the database system. 
     In an embodiment, the database system inserts records into chunks based on a time attribute of the record. Accordingly, even though a new partitioning policy is defined, the database system may receive insert requests and create chunks based on a previous partitioning policy. For example, the database system may receive some records very late (i.e., the time they are received may be significantly after the values of the records&#39; time attribute), for example, due to delay caused by network or other resources. The database system may create chunks based on an older partitioning policy for storing these records. Accordingly, the database system may enforce multiple partitioning policies at the same time, depending on the data of the records that are received and need to be inserted in a hypertable. 
       FIG. 9  illustrates selection of partitioning policy for creating chunks based on time attribute of the record, according to an embodiment. Accordingly, independent of the time that the insert request is received, if insert requests are received with records having a time attribute value that is before the reconfiguration time T, any new chunks created for storing the records are created based on the first partitioning policy.  FIG. 9  shows a timeline  900  and various events along the time line. For example, the database system initially has three locations (disks)  910   a ,  910   b , and  910   c  and creates chunks according to partitioning policy P 1 . At reconfiguration time T, a new location  910   d  is added to the database system  110 . However, if insert requests received after reconfiguration time T have time attribute values that are before reconfiguration time T, the database system creates chunks for storing the records (if none of the existing chunks can store the records) according to the first partitioning policy P 1 . Furthermore, if insert requests received after reconfiguration time T have time attribute values that are after the reconfiguration time T, the database system creates chunks for storing the records (if none of the existing chunks can store the records) according to the second partitioning policy P 2 . Accordingly, the time interval T 1  during which chunks are created according to the first partitioning policy P 1  can extend after the reconfiguration time T. Time interval T 2  indicates the time during which chunks are created according to the second partitioning policy P 2 . 
       FIG. 10  shows a flowchart of the process for selection of partitioning policy for creating chunks based on time attribute of the record, according to an embodiment. The database system invokes the procedure shown in  FIG. 10  if the database system determines for a record being inserted that the record cannot be stored in any existing chunk and a new chunk needs to be created. The database system  110  determines  1010  the value of the time attribute of a record received for inserting in the database table. The database system  110  compares  1020  the value of the time attribute of the record with the reconfiguration time T. If the database system  110  determines that the time attribute of the record is less than the reconfiguration time T, the database system  110  creates a chunk  1030  based on the first partitioning policy P 1 . If the database system  110  determines that the time attribute of the record is greater than (or equal to) the reconfiguration time T, the database system  110  creates  1040  a chunk based on the second partitioning policy P 2 . The record is stored  1050  in the chunk that is created. 
       FIG. 11  illustrates selection of partitioning policy for creating chunks based on time of receipt of a record by the database system, according to an embodiment.  FIG. 11  shows a timeline  1100  and various events along the time line. For example, the database system initially has three locations (disks)  1110   a ,  1110   b , and  1110   c  and creates chunks according to partitioning policy P 1 . At reconfiguration time T, a new location  1110   d  is added to the database system  110 . The database system selects the partitioning policy for creating chunks based on the time of arrival of the insert request (assuming no existing chunks can be used for storing records that are received for inserting in the hypertable). Accordingly, after reconfiguration time T (i.e., during time interval T 2 ), chunks are created according to the second partitioning policy P 2  whereas before reconfiguration time T (i.e., during time interval T 1 ), chunks are created according to the first partitioning policy P 1 . Accordingly, the partitioning policy selected for creating chunks is selected independently of the value of the time attribute of the records being inserted. For example, if for any reason records having time attribute values that correspond to time occurring before reconfiguration time T arrive late, i.e., after reconfiguration time T, the database system creates chunks according to the second partitioning policy P 2  for storing the records. Accordingly, records with time attribute value less than reconfiguration time T can be stored in chunks created according to either partitioning policy P 1  or P 2 . 
     In some embodiments, the database system continues to insert records into a chunk that was created before reconfiguration time T even if the insert request arrives after reconfiguration time T so long as the time attribute of the record corresponds to the time range for the chunk. In other embodiments, the database system modifies an existing chunk that was created according to the first partitioning policy P 1  so as to reduce the time range (if necessary) to correspond to the latest record inserted into the chunk. For example, if the insert request&#39;s arrival time is 5:30 am and the chunk&#39;s current time range is until noon, the database system identifies the record with the highest value for its time attribute in that chunk. Assuming that the record with the highest time value in that chunk has a time of 5:45 am, the database system modifies the end of the chunk&#39;s time range to a time greater than or equal to 5:45 am, for example, 6 am. Subsequently, if the database system receives a record at time greater than 6 am, the database system creates a new chunk according to the new partitioning policy P 2  starting at 6 am. 
     In some embodiments, the database system may create overlapping chunks as a result of reconfiguration of the system. The database system enforces a policy that after reconfiguration of the system, the database system does not insert records in chunks created based on the first partitioning policy P 1 . As a result, after reconfiguration of the system, the database system creates a new chunk for storing a record based on partitioning policy P 2 , even if there is an existing chunk created based on policy P 1  that maps to the dimension attributes of the record. As a result, a record having a particular dimension attribute could potentially be stored in a chunk C 1  created based on the first partitioning policy P 1  or in a chunk C 2  created based on the second partitioning policy P 2 . As a result, chunks C 1  and C 2  are overlapping such that a record could map to both chunks C 1  and C 2 , If the database system subsequently receives queries that process a particular record R, the database system  110  determines whether the record R was stored in a chunk created based on the first partitioning policy P 1  or the second partitioning policy P 2 . Accordingly, the database system  110  may have to check two possible chunks to determine where the record R is stored. 
     In some embodiments, the database system  110  creates the new chunks that overlap old chunks in terms of the time range used for partitioning the records. As a result, even after creation of a new set of chunks responsive to the addition of new locations, the database system may insert records into old chunks that were created before the addition of the locations. While this may involve the old chunks (from the old view) continuing to see some fraction of new inserts—although this can be mitigated based on the insert policy for overlapping chunks, e.g., one such policy prefers inserting new records to the smaller-sized chunk—this overlap will not continue into future intervals. For example, continuing with the above example, when the database system creates the new chunks 9 hours into the existing chunks&#39; interval, it sets the start and end times for the new chunks to be the same as the existing chunks (i.e., 9 hours ago and 3 hours hence). But, because the database system can employ a policy to write to smaller-sized chunks, for example, inserts will be made to the new chunks rather than the existing ones, even though the two sets have overlapping time periods. 
     In embodiments of the database system that use a purely size-based approach to determining when to close a chunk, these time interval issues do not arise, and the database system then simply closes the existing chunks (even when their size at the time of system reconfiguration may be smaller than the standard threshold size) and creates new ones using the new partitioning policy. 
     Because the new view may maintain a different set of partitions, the database system may maintain additional metadata that associates each of these reconfigurations into an “epoch.” In particular, each epoch may be associated with various information, including a time period, the set of partitions, and a system view. Then, as described above, in order to determine a hypertable&#39;s partitions at a particular time, the database system might need to first determine the epoch associated with the time, then determine the partitions associated with this epoch. This process is described above in the context of an insert method that the database system employs. 
     Invalidation 
     In some embodiments, the invalidation engine  190  uses triggers to intercept DML statements and record the minimum and maximum values affected. In other embodiments, the statements may be intercepted by reading the database replication stream or any other means of tracking changes to the raw data. In other embodiments, the logic for tracking invalidation is simply part of the DML logic itself. 
     When multiple materializations exist, either hierarchically or not, the invalidation engine  190  may process and record invalidation information per base table or per materialization (or in some cases, both). For instance, in the above example, the invalidation log and/or thresholds may be kept per base table or per materialization, or, for instance, thresholding may be used individually for both while the invalidation log is kept in common. Additionally, in some embodiments, the invalidation events may be recorded once for the base table, but then moved asynchronously to invalidation logs for the individual materializations. This allows the recomputation/correction to happen independently for each materialization while the invalidations are maintained for each until that can be accomplished. Writing the per-materialization invalidations asynchronously means less latency during DML operations as there is less information to write during the DML operation. 
     In some embodiments, specifically those using hypertables and chunks, the invalidation events may be defined per chunk or per hypertable. Tracking invalidation events per chunk allows for simpler job decomposition for the materialization engine, as it can assign work on a per-chunk basis rather than across the entire hypertable. 
     To maintain transactional consistency in some embodiments, the invalidation engine  190  runs as part of the transaction that modifies the data. In other embodiments in which eventual consistency is preferred, the invalidation engine  190  may run outside of the transaction context and invalidate data in a more “lazy” manner. 
     In some embodiments where the database system is spread across multiple machines, the invalidation engine  190  keeps invalidation information locally on a server, while in others the invalidation engine  190  sends this invalidation information to other remote servers. 
     Invalidations may also occur for base tables lacking time attributes in their records. One example of this is when a materialized view contains a join between a time-series table and a metadata table and a row in the metadata table is updated. In one embodiment, the invalidation system may add another invalidation record types that invalidates all values for a particular column or field in table records. The materialization engine may need to recompute all materializations with this field value. If this field is a group-by field, the materialization engine may be able to recompute this efficiently by only recomputing the materialization only for that group-by value. In another embodiment, the invalidation may try to simply modify any aggregates that contain the value by searching for rows that reference the modified metadata row in the base table. In other embodiments, the semantics of that base table and/or materialized data is such that modifications to metadata should only affect rows after (or before) a certain timestamp. In that case, the invalidation engine makes use of that timestamp to reduce the data that is invalidated. 
     One such example of a materialized table created by joining the base table as described earlier with the following base table: 
     
       
         
           
               
               
             
               
                   
                   
               
             
            
               
                   
                 CREATE TABLE devices ( 
               
            
           
           
               
               
            
               
                   
                 device_id TEXT NOT NULL, 
               
               
                   
                 device_type TEXT NOT NULL, 
               
               
                   
                 Region TEXT NOT NULL 
               
            
           
           
               
               
            
               
                   
                 ); 
               
               
                   
                 CREATE VIEW minutes_region AS 
               
            
           
           
               
               
            
               
                   
                 SELECT time_bucket(‘1 minute’, time) as minute, 
               
            
           
           
               
               
            
               
                   
                 d.region 
               
               
                   
                 min(temperate) as min_temperature, 
               
               
                   
                 avg(temperate) as avg_temperature, 
               
               
                   
                 max(temperate) as max_temperature, 
               
               
                   
                 min(humidity) as min_humidity, 
               
               
                   
                 avg(humidity) as avg_humidity, 
               
               
                   
                 max(humidity) as max_humidity, 
               
               
                   
                 FROM raw r INNER JOIN devices d on r.device_id = 
               
               
                   
                 d.device_id 
               
               
                   
                 GROUP BY minute, d.region; 
               
               
                   
                   
               
            
           
         
       
     
     In such an example, modifications to the devices table may affect the aggregations stored in the materialized view. 
     Some embodiments combine strategies based on the time represented in the base table&#39;s raw data. For instance, the database system may divide table data into three segments based on time: (i) the most recent data (e.g. more recent than 1 day), (ii) intermediate data (e.g. up to a month ago), and (iii) old data (e.g. older than 1 month). For the most recent data, the database system may not materialize anything, and so the system need not perform any invalidation. For intermediate data, the system can create invalidation information and re-materialize asynchronously in a background process. Finally, for old data, changes may be very rare, so that when changes do occur, the database system may re-calculate and update the materialization synchronously with the modifications. In some embodiments, different strategies are defined on a per-chunk basis within a hypertable. 
     Choosing the Region to Materialize 
     The materialization engine needs to choose which regions of the base table&#39;s data to materialize. Commonly, this consists of any new regions that have never been previously materialized, as well as any regions that need to be re-materialized due to invalidation. 
     In many embodiments, the user is able to configure how far behind the materialization system should operate (e.g., no more or at least one hour behind the latest record or the current time), which we sometimes refer to as the lag interval. This lag interval may be a hard limit of some sort, or it may be a soft target in terms of time or amount of change. The materialization engine interacts with these configurations to determine how often it should compute materializations, how big each materialization job should be (e.g., the range of records that one job processes), and so forth. 
     In some embodiments, this lag interval provides an upper-bound for how up-to-date the materialized table is with respect to the base table. In such a setting, for example, if the lag interval is one hour, then the materialization engine only selects records from the base table to materialize to the materialized table provided the record&#39;s timestamp is less than or equal to the minimum time threshold defined by lag interval. In some embodiments, this time threshold is calculated by an offset behind current time (e.g., if the lag interval is one hour and the current time is UTC time 12:30:00 pm, then the lag interval&#39;s minimum time offset is UTC 11:30:00 am). In other embodiments, this time threshold is calculated by an offset behind the base table&#39;s record with the maximum timestamp (e.g., if the lag interval is one hour and the record with the maximum timestamp has a timestamp of UTC 12:20:00 pm, then the lag interval&#39;s minimum time offset is UTC 11:20:00 am). 
     In other embodiments where the lag interval is a soft target in terms of amount of change, the database system tracks the extent of changes subsequent to the completion threshold. In some such embodiments, the lag interval is defined in terms of some number of records that have timestamps greater than or equal to the current completion threshold. For example, if the lag interval is 20 records and the completion threshold is at UTC 11:30:00 am, and 50 new records are inserted to the base table with timestamps greater than or equal to 11:30:00 am, then in some embodiments the materialization engine will materialize the region covering the next 30 records that follow the completion threshold in timestamp order. In some embodiments, the database engine uses a minimum time threshold to track such soft targets, e.g., maintaining a threshold near or at the timestamp of the input record that is 20 records behind (in decreasing timestamp order) the record with the maximum timestamp in the base table, and then materializing the region covering the records between the completion threshold and this minimum time threshold associated with the lag interval. 
     In some embodiments, the materialization engine reads information produced by the invalidation engine in order to know which regions of data to re-materialize in its current run. For embodiments that store a single invalidation threshold, the materialization engine recomputes its materialization on data between the invalidation threshold and the current time (or lag interval if present), although in some embodiments materialization may start at a region before or near the invalidation threshold for certain types of computations. For embodiments that store an invalidation range, the materialization engine recomputes its materialization on data between (or near) the range specified by the invalidation information. 
     In embodiments that have multiple invalidated ranges, the materialization engine can operate in several different manners. It can recompute individual invalidated ranges separately, or as a larger operation or transaction. It can combine overlapping ranges into larger invalid ranges, which it can subsequently process, so that it doesn&#39;t reprocess individual ranges multiple times. Even if ranges are close to one another but not overlapping, it can combine them into a larger invalid range for processing, e.g., given alignment of the ranges to certain boundaries, such as a specific time interval or time bucket. It can also split overly large invalidation ranges into smaller ranges for separate processing. 
     In some embodiments, the materialization engine chooses a new region of data to materialize along with the ranges derived from the invalidation information in one operation or transaction. In other embodiments, the system materializes new and invalidated regions in separate operations or transactions. 
     The materialization engine may choose to operate in such manner in order to optimize for load balancing; cost reasons; disk, CPU, or memory utilization; state or resource management; latency or throughput optimizations; or other reasons. 
     Managing Data Access for Materialization 
     If the invalidation engine uses an invalidation threshold, the materialization engine needs to modify this threshold before or as part of reading data from the raw data. 
     In some embodiments, the system preserves the invariant that, given a data modification process that changes records in the base table and a materializing process that performs a materialization from this base table, either the materialization process will see any modifications performed by data modification process when reading the base table, or the data modification process will see a invalidation threshold that is equal to or higher than any data read by the materialization process (and will thus record an invalidation entry). 
     In one embodiment, the materialization engine, before reading any of the data from the base table (or other materialized tables), begins a transaction, takes some locks, and moves the invalidation threshold up to the maximum time value it will read. Then, the materialization engine commits the transaction and releases the locks. The locks that this transaction took must have conflicted with any data modification process, which would have prevented any currently running data modification process from seeing the old threshold. Conversely, it also guarantees that the materialization engine will see any data modifications performed by any process that saw the old threshold when it subsequently reads the base table. Note also that this transaction performs as few actions as possible, so that the system does not block data modifications transactions for too long. After this first transaction is committed, the materialization engine will start a new transaction for reading the raw data and performing the materialization. In another embodiment, the materialization engine can move up the invalidation threshold and perform the materialization in a single transaction. One of ordinary skill would also recognize that alternative mechanisms or techniques could be used in place of locks to manage concurrency control or multi-threaded/multi-process operation, such as semaphores, latches, advisory mechanisms, system coordinators, or other approaches. 
     Performing the Materialization 
     To perform the materialization, the materialization engine runs a query on the base table (or other materialized tables) over a range to materialize, and writes the results to the materialization table. If using an invalidation log, the materialization engine will delete all the entries in the invalidation log for which range was re-materalization (often in the same transaction). 
     If data from that re-materialized range already exists in the materialization table, the materialization engine can overwrite the existing data as part of the process or transaction, e.g., via a delete-then-insert, update, or upsert. Finally, the materialization moves the completion threshold (or interval) up to the maximum time (or widest interval) that it processed. 
     In one embodiment, the materialization engine may be run in a separate background process within the database. The execution of a materialization by the materialization engine may be triggered by a timer, some interaction with the invalidation engine (e.g., once some number of changes or invalidation ranges have been made), or other means. In some embodiments, the materialization engine is triggered as a result of certain DML, DQL, or DDL operations. In some embodiments, trigger functions is called after a single or batch of DML operations which will cause the materializations to be updated. In other embodiments, the materialization engine is run in conjunction with the query processor, so that when a query is first processed, its results will also be materialized. In some such embodiments, the materialization happens lazily, after a client first requests a given query. 
     Storing the Materialization 
     The format and types of the data stored in the materialization may be different in different embodiments. For instance, in some embodiments, partial aggregate states are stored which can be re-combined to create accurate aggregations for data at higher levels. This may entail storing extra data in some cases; for instance, in lieu of storing an average, the count and sum can be stored, which can then be combined with other counts/sums in order to create higher-level accurate averages, even though this requires storing two values rather than a single value. 
     In some embodiments, explicit computations and extractions of partial data types may be accomplished through the creation of functions for that purpose, or functions that already exist in the underlying database system may be used. Wrapper functions which call underlying functions may also be used to extract or recombine partial results. 
     In some embodiments, the storage system for materializations is different from the storage system for the raw data from base tables. For instance, a columnar store can be employed for materializations while a row store can be used for the raw data. This can also include storage of the data on other disks or even other machines, or include storage in different storage formats, such as compressed vs. uncompressed data. In some embodiments involving partitioned storage, different partitioning schemes may be used for the aggregated data compared to the raw data. In addition, the partitioning keys used by the raw data may or may not be included in the grouped by or aggregated by columns included in the materialization. In some embodiments, the time column is always included in the materialization (even if only implicitly included, which means if a roll up is taken over all time, it can still be broken out and invalidated based on subsets of time). 
     Materializations may be stored in the same logical or physical disk or node as the base table (or the materialized table to which it is based), or they may be stored in separate logical or physical disks or nodes. In addition, they may be part of the same database or other software program, or they may be stored and accessed by a separate program. 
     In some embodiments, the storage system for materializations allows for further indexing and other sorts of optimizations, the creation and use of such indexes may be mediated by the user or performed automatically (e.g., based on the base table and its indices), or they may be created automatically (e.g., through an analysis of user query behavior). 
     In some embodiments, aggregates are kept at multiple granularities of time intervals or buckets. In some cases, the lower levels of aggregation (e.g., 1 minute) are full subsets of the higher levels (1 hour) and may be used to populate the higher-level aggregates. Materialization may occur simultaneously or as a derivation from lower-level materializations. The storage may be combined into one underlying store, for instance in a tree structure or other such representation, as separate overlapping rows which have some means to avoid double counting at query time, or they may be stored as separate materializations. 
     In addition to multiple granularities in time, multiple rollups may exist (typically defined as aggregations which group by different subsets of columns in the base table). These rollups may be either disjoint sets or some rollups may be subsets of others. Different storage strategies may be used, including tree based structures with partial rollups stored at each level for subgroups, multi-level rollups stored in the same materialization with markers (such as nulls) for columns which are at higher granularity, and/or separate materialization tables for each set. 
     Different aspects of these embodiments may be combined with one another in a single embodiment, where the strategy is selected based on time or some other partitioning parameter. In some embodiments, these strategies are assigned and/or modified on a per chunk basis. For example, a strategy that has significant write amplification but minimal impact on query speed may be chosen for older chunks (which generally have fewer writes directed to them), whereas a strategy which privileges writes may be selected for newer data (which has higher write volumes and is more likely to be in memory, so query speed may be less affected by materialization). 
     The Materialization Engine 
     In some embodiments, the materialization engine runs in a process or database system separate from the database process where the base table and/or materialization table are stored. Such processes connect to the database to perform necessary tasks, such as its calculations and the DML operations affecting the materialized output. In some similar embodiments the materialization engine consumes changes to the base data using a replication protocol exposed by the database, then proceeds to connect to the database to modify the materializations (on a timer or after some amount of data has been consumed, for instance). This is performed in continuous streaming fashion or in batches. 
     In other embodiments, the materialization engine runs on a local machine and only materializes data to the same node, whereas in others the materialization engine may materialize data by acting through the normal data modification path exposed by the cluster (some combination of these two strategies may also be used in clustered environments). 
     When multiple materializations exist for a single base table, the materialization engine may populate all of the materializations simultaneously, or it may launch separate instances of the materialization engine or other type of job to populate each materialization. 
     In some embodiments, the materialization engine is comprised of several subcomponents that perform specific functions, such as a range selection and combination component (to determine what regions of data are invalid and what work should be done), a transactional control component (which properly controls interaction with the rest of the database and particularly the invalidation engine so that invalidations are done properly during the period where materializations are being performed), and the execution engine component (which performs the aggregates and populates the materializations). 
     As an example, in embodiments where the materialization engine consumes changes to the database via a replication mechanism, the transactional control component controls when consumed changes finalized, which can cause the materialization engine to track any further changes that come in after a certain point in a separate data structure to be written in the next pass through. This would also control any interaction needed to synchronize that with the invalidation engine, so that both systems remain in sync. 
     Query Processing Engine 
     When the query processor receives a query, it can compute query results using both the raw data from the base table and the materialized data from the materialized table, particularly given knowledge of the relationship between these tables as well as the completion threshold, invalidation information, or a combination thereof. For example, consider an example in which the view is defined as above. 
     
       
         
           
               
               
             
               
                   
                   
               
             
            
               
                   
                 CREATE VIEW minutes AS 
               
            
           
           
               
               
            
               
                   
                 SELECT time_bucket(‘1 minute’, time) as minute, 
               
            
           
           
               
               
            
               
                   
                 device_id, 
               
               
                   
                 min(temperate) as min_temperature, 
               
               
                   
                 avg(temperate) as avg_temperature, 
               
               
                   
                 max(temperate) as max_temperature, 
               
               
                   
                 min(humidity) as min_humidity, 
               
               
                   
                 avg(humidity) as avg_humidity, 
               
               
                   
                 max(humidity) as max_humidity, 
               
            
           
           
               
               
            
               
                   
                 FROM raw 
               
               
                   
                 GROUP BY minute, device_id; 
               
               
                   
                   
               
            
           
         
       
     
     The materialization is done asynchronously and lags behind the current time by 5 minutes. In such a scenario, a query for the last hour can look up the completion threshold for the materialized table and execute the query on the materialized table up until the completion threshold and combine that result with data for the base table that has happened since the completion threshold, as shown in  FIG. 12A . 
     Further, the query processor can use the invalidation log to detect regions of the time dimension that have been invalidated and substitute data from the base table there as well, as shown in  FIG. 12B . In some embodiments of such scenarios, the query processor will determine the regions of the materialized table for which no invalidation regions exist, and then in response to a query, generates results from the base table that includes both regions of the base table after the completion threshold as well as regions of the base table corresponding to invalidation regions, and combines those results from the base table with results from the materialized table for regions for which no invalidation regions exist. In such a manner, the query processor ensures that the results of a query reflect the current state of the database. 
     In some embodiments, the query engine only uses materialized data if the query is for the materialized view. In other embodiments, the query engine also opportunistically uses the materialized data if the query is against the base table, provided that it is determined that the materialized data can be used to fulfill (part of) the query. 
     The query processor may use various logic to determine what part of the data to get from the materialized table and what data to get from the base table. For instance, this logic can be cost-based or heuristic planning. Further, it can use information about the accuracy of materialization data to make this determination. For instance, the system can keep statistics or sketches reflecting how different the materialization data is from the base table&#39;s raw data or it may keep information about the staleness of the materialization. This complex logic may also choose among multiple materializations if they are available and also choose a combination of the materializations. Such logic may also be used when a materialized in based on another materialization (as well as other complex dependencies or further hierarchical materializations). 
     In some embodiments with hierarchical materializations, materialized tables can be based on other materialized tables, which in turn can be based on other materialized tables or the base table. In the case of hierarchical materializations, inserts or changes to the base table will be reflected in the one or more materialization tables associated with the base table. Correspondingly, those subsequent changes to this first set of materialization tables will in turn become reflected in any other materialization tables which depend on the tables within this first set. These hierarchical materializations can perform different types of aggregation, sampling, or approximation as the data moves up the hierarchy. In one example, a base table stores data at a timestamp granularity in terms of seconds, a first materialization table associated with it stores records that compute aggregate statistics over the raw data at an hour granularity (e.g., the average, min, and max per hour), and a second materialization table associated with the first materialization table stores records that compute aggregate statistics over the minutely data at a weekly granularity (e.g., the average, min, and max per hour). Additionally, a third materialization table can also be associated with the base table to compute some other data at a minutely granularity (e.g., storing some other aggregate or statistical information about the base table&#39;s data, or sampling some random number of records per minute). And a fourth materialization table can be associated with the first materialization table to compute additional, alternate hourly statistics on the secondly data. In short, hierarchical materializations allow a rich and flexible set of associations between tables, including hypertables. 
     With such hierarchical materializations, the database system will maintain various metadata for the materialized tables that other materialized tables are associated with (e.g., including invalidation intervals and records, invalidation thresholds, completion thresholds, lag intervals, etc.), akin to the various metadata for the base table described herein. In other words, this metadata serves to ensure that inserts, queries, materialization, and invalidation properly work not only from the base table to a first materialized table, but similar metadata on the first materialized table serves to ensure that inserts, queries, materialization, and invalidation properly works from the first materialized table to a second materialized table. 
     In some embodiments, the query processor starts a query accessing the base table and one accessing the materialization table concurrently, and return with the first that returns results. In some embodiments, the query processor starts the query on the base table and only switch to using the materialized table once the query has taken some amount of time. 
     When combining raw and materialized data, the query processing typically operates to ensure that the result of the combination is the same as the result on the base table&#39;s raw data itself. In order to facilitate this, in many embodiments, the materialized data often contains the partialized state of the aggregate instead of the final state. For example, when calculating the average of a set of values, the state materialized contains the sum and count pair instead of the finalized aggregate. In this way, the query processor or materialization engine can combine the sums and counts for the same group coming from the materialized and base tables, and then calculate the final average by dividing the sums by the counts. Partialized states for multiple aggregates may even have overlapping parts, in which case a single partialized state may be stored and used by multiple different computations. 
     In some embodiments, there are multiple different materialized views on the base table, or materialized views based on other materialized views, and the query processor combines results from the base table and the multiple materialized views to give the final result. In some embodiments where the different materialized views can have different time bucket granularities, the query processor can choose to use the coarsest granularity first for all regions of the data space that are covered by it, then switch to increasingly finer granularities for other regions, and finally use the base table for any regions not covered by any of the materialized data. 
     For example, consider a database system with a first materialized view with a minute time bucket based on raw data, and a second materialized view with an hour time bucket based on the first materialized, and further consider the first materialized view having a completion threshold of 5 minutes before the current time, and the second materialized view having a completion threshold of 1 hour before the current time. Then, for a query asking for hourly data covering the last 24 hours, the query processor can use the second materialized view to read pre-computed hourly data for 23 hours, and then combine that data with the final hour&#39;s result, which the query processor calculates at query time by combining minutely data from the first materialization covering 55 minutes with raw data from the final 5 minutes. (This example assumes that none of these materialized table has any invalidated regions, in which case the query processor&#39;s calculation could be different and involve base tables for invalidated regions, as described herein.) 
     In some embodiments, the query processor only uses data from different materialization if the regions they cover do not overlap. In others, overlapping may be allowed and an approximation used. Similarly, some embodiments may use materialized data if the region covered by the materialization is fully contained within the query-space. In other embodiments, approximations may be used. 
     In some embodiments, the query processor can choose query-space regions for different materializations and the base table on dimensions different than just the time dimension. For example, the query processor can take into account when choosing regions other qualifiers or group-by conditions in a supplied query. In some embodiments, all of the group-by dimensions are used for this analysis, while others use only a subset, and in still others the query processor uses non-group-by dimensions. 
     In some embodiments, the query processing engine interacts with the query parser, rewriter, planner, and/or executor of the database, while in others it exists as a more “standalone” system. In some embodiments, it interacts with the materialization engine and/or invalidation engines; for instance, it may send the results of a query to the materialization engine if it determines that it has performed calculations that the materialization engine can use. In other embodiments, it only interacts with the outputs of the invalidation and materialization engines, not directly with them. 
     Replica Management 
     In some embodiments, the database system is distributed across multiple physical machines (which we also refer to as nodes). In such cases, the materialized tables can be distributed in multiple ways among different nodes and disks. The query processor can communicate with different nodes in the system to read data from different materialization tables (or replicas thereof) and different base tables (or replicas thereof). 
     When the base table is itself partitioned across many nodes (e.g., as in a hypertable), the materialization table can also be partitioned across many nodes (including using a hypertable for the materialization table). Each partition of the materialization table can be colocated with the base table partition on which it is derived, or it can be on a different node. A non-partitioned materialization table can also be based on a partitioned base table, or vice versa. One of ordinary skill will recognize that there are multiple ways to lay out materialized tables and base tables across the nodes belonging to the database system, when the tables are either partitioned or not. 
     In some embodiments, the materialized tables is computed once at some node in the system and then replicated to other nodes. This replication can be performed by replicating the entire database running on that node to other nodes (e.g., via streaming replication), or it can be performed by replicating only the materialization table to other nodes (e.g., via logical table replication). 
     In some embodiments, the materialization table is not replicated at all but computed locally on the nodes that have the raw data. In this case, the materialization table can be stored on the same node as the base table or shipped to another node after computation. In such an embodiment, each node may independently determine when to schedule materializations and other potentially costly operations so that if one node faces high load, they can avoid writing materializations until later. It is also possible for the node performing the materialization to be different than the one storing the base table and/or the materialized table. 
     The materialization table may be replicated a different number of times than the base table and to different nodes than the base table. It is important to note that the materialization table data can be re-computed from the raw data and so can be replicated fewer times than the raw data itself. This can be done without loss of data safety and can save the database system from performing additional work or additionally replicating data, although query performance may degrade if a materialization is unavailable. 
     If a materialization table is replicated, each replica may have different properties or characteristics, such different types or numbers of indexes, different orderings of data on disk (e.g., by a clustered index), different storage formats, storage layouts, types of disks, types of compression, and so forth. The query processor can use these differences to derive more optimal execution plans when selecting being replicas to execute the query. 
     When materializations are stored separate from the underlying data store, they may perform their own replication using various protocols or may be re-calculated on each node. 
     Retention Management 
     In some embodiments, the database system includes a retention management engine that deletes or archive raw data from a base table used to populate materializations. When archiving data, the retention management engine can replicate or copy the data to another storage system outside of the database system, in either a like or transformed form as stored in the database, before deleting the data from the base table. The retention management engine can also perform such deletions or archiving on materialization tables, including those that have materialization tables based on them. 
     In such embodiments, when data is deleted from a base table, the corresponding data that depends on the deleted data in one or more materialization tables is corresponding deleted as well. In some embodiments, this type of cascading deletes occurs from a data deletion configuration policy defined within the database or on specific tables, or as a result of a specific user or system command when performing those deletion actions. 
     In other embodiments, when deleting data, the retention management engine can still preserve the materializations that are based on the deleted data. To do so, the engine may modify metadata or other system information to take special action on DML operations, invalidation events, and queries to the regions for which raw data has been removed. 
     This retention management engine can run on the same nodes on which the tables are stored, or it can be executed on nodes external to the data. In some embodiments, new DML statements are added to define retention policies or actions. In some embodiments, retention actions may be scheduled by background processes or processes outside of the database system. 
     Retention policies may affect any region of a table, including based on a time region or regions based on other dimensions or attributes of the table&#39;s records. Different actions may need to be taken by the retention management engine depending on whether the region is defined on a dimension used for table partitioning of either the base or materialization tables. 
     In some embodiments, materialized data that has had its underlying raw data deleted or archived may be moved to a separate store, or marked in some way as different from other materialized data. The query processing engine may introduce functionality to include this data, combining it with the raw and other materialized data in order to return correct results to the user. 
     In some embodiments, regions of data affected by retention policies have different DML semantics, i.e., how they are affected by insert, update, delete or other change requests. For example, DML operations on such regions may be blocked altogether, only a subset of modifications may be allowed, or modifications may only be allowed in special circumstances. In some embodiments, this is implemented as part of the invalidation engine. 
     In some embodiments, invalidated materializations or materializations not yet completed may need to be calculated before the raw data is deleted, to ensure that materializations are fully accurate before the raw data disappears. In some embodiments, the properties of the materialization may need to be changed or some additional actions performed before the raw data is deleted. For instance, the replication factor of the materialized data may need to be increased as it can no longer be easily derived from the replicated data; the system may make sure the data is sufficiently replicated before deleting the raw data. 
     In some embodiments, multiple materializations at different granularities are stored using different retention periods. Some of these materializations may be derived from previous materializations and may have different logic as such. 
     Architecture of Computer for a Database System 
       FIG. 13  is a high-level block diagram illustrating an example of a computer  1300  for use as one or more of the entities illustrated in  FIG. 1 , according to one embodiment. Illustrated are at least one processor  1302  coupled to a memory controller hub  1320 , which is also coupled to an input/output (I/O) controller hub  1322 . A memory  1306  and a graphics adapter  1312  are coupled to the memory controller hub  1322 , and a display device  1318  is coupled to the graphics adapter  1312 . A storage device  1308 , keyboard  1310 , pointing device  1314 , and network adapter  1316  are coupled to the I/O controller hub. The storage device may represent a network-attached disk, local and remote RAID, or a SAN (storage area network). A storage device  1308 , keyboard  1310 , pointing device  1314 , and network adapter  1316  are coupled to the I/O controller hub  1322 . Other embodiments of the computer  1300  have different architectures. For example, the memory is directly coupled to the processor in some embodiments, and there are multiple different levels of memory coupled to different components in other embodiments. Some embodiments also include multiple processors that are coupled to each other or via a memory controller hub. 
     The storage device  1308  includes one or more non-transitory computer-readable storage media such as one or more hard drives, compact disk read-only memory (CD-ROM), DVD, or one or more solid-state memory devices. The memory holds instructions and data used by the processor  1302 . The pointing device  1314  is used in combination with the keyboard to input data into the computer  1300 . The graphics adapter  1312  displays images and other information on the display device  1318 . In some embodiments, the display device includes a touch screen capability for receiving user input and selections. One or more network adapters  1316  couple the computer  1300  to a network. Some embodiments of the computer have different and/or other components than those shown in  FIG. 13 . For example, the database system can be comprised of one or more servers that lack a display device, keyboard, pointing device, and other components, while a client device acting as a requester can be a server, a workstation, a notebook or desktop computer, a tablet computer, an embedded device, or a handheld device or mobile phone, or another type of computing device. The requester to the database system also can be another process or program on the same computer on which the database system operates. 
     The computer  1300  is adapted to execute computer program modules for providing functionality described herein. As used herein, the term “module” refers to computer program instructions and/or other logic used to provide the specified functionality. Thus, a module can be implemented in hardware, firmware, and/or software. In one embodiment, program modules formed of executable computer program instructions are stored on the storage device, loaded into the memory, and executed by the processor. 
     Additional Considerations 
     In time-series workloads, writes are typically made to recent time intervals, rather than distributed across many old ones. This allows the database system  110  to efficiently write batch inserts to a small number of tables as opposed to performing many small writes across one giant table. Further, the database systems&#39; clustered architecture also takes advantage of time-series workloads to recent time intervals, in order to parallelize writes across many servers and/or disks to further support high data ingest rates. These approaches improve performance when employed on various storage technologies, including in-memory storage, hard drives (HDDs), or solid-state drives (SSDs). 
     Because chunks are right-sized to servers, and thus the database system does not build massive single tables, the database system avoids or reduces swapping its indexes to disks for recent time intervals (where most writes typically occur). This occurs because the database system maintains indexes local to each chunk; when inserting new records into a chunk, only that chunks&#39; (smaller) indexes need to be updated, rather than a giant index built across all the hypertable&#39;s data. Thus, for chunks associated with recent time intervals that are regularly accessed, particularly if the chunks are sized purposefully, the chunks&#39; indexes can be maintained in memory. Yet the database system can still efficiently support many different types of indexes on different types of columns (e.g., based on what is supported by each node&#39;s database engine, such as PostgreSQL), including B-tree, B+-tree, GIN, GiST, SP-GiST, BRIN, Hash, LSM Tree, fractal trees, and other types of indexes. 
     The database system combines the transparent partitioning of its hypertable abstraction with a number of query optimizations. These optimizations include those which serve to minimize the number and set of chunks that must be contacted to satisfy a query, to reduce the amount of records that are transferred back from a query that touches a chunk, to specify whether raw records or aggregates results are transferred back from a chunk, and so forth. 
     Common queries to time-series data include (i) slicing across time for a given object (e.g., device id), slicing across many objects for a given time interval, or (iii) querying the last reported data records across (a subset of) all objects or some other distinct object label. While users perform these queries as if interacting with a single hypertable, the database system leverages internally-managed metadata to only query those chunks that may possibly satisfy the query predicate. By aggressively pruning many chunks and servers to contact in its query plan—or during execution, when the system may have additional information—the database system improves both query latency and throughput. 
     Similarly, for items like unique devices, users, or locations, the database system may receive queries like “select the last K readings for every device.” While this query can be natively expressed in SQL using a “SELECT DISTINCT” query (for finding the first or last single value per distinct item) or via windowing functions (for finding K such values), such a query can turn into a full table scan in many relational databases. In fact, this full table scan could continue back to the beginning of time to capture “for every device”, or otherwise either sacrifice completeness with some arbitrarily-specified time range or involve a large WHERE clause or JOIN against some set of devices of interest (which may be maintained in a manual or automated fashion). 
     In some embodiments, the database system maintains additional metadata about a hypertable&#39;s fields in order to optimize such queries. For example, the database system records information about every distinct (different) value for that field in the database (e.g., the latest row, chunk, or time interval to which it belongs). The database system uses this metadata along with its other optimizations, so that such queries for distinct items avoid touching unnecessary chunks, and perform efficiently-indexed queries on each individual chunk. The decision to maintain such metadata might be made manually or via automated means for a variety of reasons, including based on a field&#39;s type, the cardinality of the field&#39;s distinct items, query and workload patterns, and so forth. 
     The database system may perform other query optimizations that benefit both single-node and clustered deployments. When joining data from multiple tables (either locally or across the network, e.g., via foreign data wrappers), traditional databases may first select all data matching the query predicate, optionally ORDER the data, then perform the requested LIMIT. Instead, the database system  110  first performs the query and post-processing (e.g., ORDER and LIMIT) on each chunk, and only then merges the resulting set from each chunk (after which it performs a final ordering and limit). 
     The database system  110  uses LIMIT pushdown for non-aggregate queries to minimize copying data across the network or reading unnecessary data from tables. The database system also pushes down aggregations for many common functions (e.g., SUM, AVG, MIN, MAX, COUNT) to the servers on which the chunks reside. Primarily a benefit for clustered deployments, this distributed query optimization greatly minimizes network transfers by performing large rollups or GROUP_BYs in situ on the chunks&#39; servers, so that only the computed results need to be joined towards the end of the query, rather than raw data from each chunk. In particular, each node in the database system performs its own partial aggregation, and then only return that result to the requesting node. 
     For example, if the query to the database system requests some MAX (maximum value), then the first node processing the hypertable query sends MAX queries to other nodes; each receiving node performs the MAX on its own local chunks before sending the result back to the first node. This first node computes the MAX of these local maximum values, and returns this result. Similarly, if the hypertable query asks for the AVG (average), then the first node sends queries to other servers that ask for the sum and count of some set of rows. These nodes can return their sums and counts to the first node, which then computes the total average from these values (by dividing the sum of sums by the sum of counts). 
     The database system computes joins between hypertables and standard relational tables. These standard tables can be stored either directly in the database system or accessed from external databases, e.g., via foreign data wrappers. 
     The database system  110  performs joins between two hypertables, including in a number of ways involving distributed optimizations, e.g., distributed joins. Such optimizations include those using hash-based partitioning, as well as those that carefully minimize data copying by only sending data from one hypertable&#39;s chunks to the servers with the other&#39;s chunks according to the join being performed, optionally leveraging the metadata associated with the chunk. Such optimizations also include placing the chunks of hypertables that will be regularly joined on servers in a way that like keys or key ranges are commonly collocated on the same server, to minimize sending data over the network during joins. 
     The database system allows for easily defining data retention policies based on time. For example, administrators or users can use explicit commands or configure the system to cleanup/erase data more than X weeks old. The system&#39;s chunking also helps make such retention policies more efficient, as the database system then just drops entire chunks (internal data tables) that are expired, as opposed to needing to delete individual rows and aggressively vacuum the resulting tables, although the database system does support such row-based deletions. 
     For efficiency, the database system enforces such data retention policies lazily. That is, individual records that are older than the expiry period might not be immediately deleted, depending upon policy or configuration. Rather, when all data in a chunk becomes expired, then the entire chunk is dropped. Alternatively, the database system uses a hybrid of dropping chunks and deleting individual rows when performing data deletions or adhering to data retention policies. 
     The foregoing description of the embodiments of the invention has been presented for the purpose of illustration; it is not intended to be exhaustive or to limit the invention to the precise forms disclosed. Persons skilled in the relevant art can appreciate that many modifications and variations are possible in light of the above disclosure. 
     Some portions of this description describe the embodiments of the invention in terms of algorithms and symbolic representations of operations on information. These algorithmic descriptions and representations are commonly used by those skilled in the data processing arts to convey the substance of their work effectively to others skilled in the art. These operations, while described functionally, computationally, or logically, are understood to be implemented by computer programs or equivalent electrical circuits, microcode, or the like. Furthermore, it has also proven convenient at times, to refer to these arrangements of operations as modules, without loss of generality. The described operations and their associated modules may be embodied in software, firmware, hardware, or any combinations thereof. 
     Any of the steps, operations, or processes described herein may be performed or implemented with one or more hardware or software modules, alone or in combination with other devices. In one embodiment, a software module is implemented with a computer program product comprising a computer-readable medium containing computer program code, which can be executed by a computer processor for performing any or all of the steps, operations, or processes described. 
     Embodiments of the invention may also relate to an apparatus for performing the operations herein. This apparatus may be specially constructed for the required purposes, and/or it may comprise a general-purpose computing device selectively activated or reconfigured by a computer program stored in the computer. Such a computer program may be stored in a tangible computer readable storage medium or any type of media suitable for storing electronic instructions, and coupled to a computer system bus. Furthermore, any computing systems referred to in the specification may include a single processor or may be architectures employing multiple processor designs for increased computing capability. 
     Finally, the language used in the specification has been principally selected for readability and instructional purposes, and it may not have been selected to delineate or circumscribe the inventive subject matter. It is therefore intended that the scope of the invention be limited not by this detailed description, but rather by any claims that issue on an application based hereon. Accordingly, the disclosure of the embodiments of the invention is intended to be illustrative, but not limiting, of the scope of the invention.