In general terms, a physical operator is an implementation of a relational operator. For a relational operator, there are many alternative physical operators that implement it, for instance, sort-merge and hash-join provide alternative algorithms for implementing join. The query execution engine provides generic implementations of all physical operators. Typically, each physical operator supports a uniform iterator interface that hides any internal implementation details and allows operators to be combined together. The iterator interface includes the functions: (i) open() that prepares an operator to produce data, (ii) next() that produces an output tuple, and (iii) close() that performs the final bookkeeping.
During query processing, an input query is transformed to a plan to be executed by the query execution engine. An execution plan can be thought of as a dataflow graph where the nodes correspond to the physical operators and the edges represent the data flow among the physical operators. Generally speaking, a physical operator is an implementation of a relational operator, for instance, sort-merge and hash-join are physical operators providing alternative algorithms for the implementation of join. The query execution engine provides generic implementations of all physical operators. A plan is executed by calling its physical operators in some (possibly interleaved) order. In most modern database systems, each physical operator supports a uniform iterator interface that allows an operator in the plan to get results from its input operators one tuple at a time, hiding the internal implementation details of each operator.
The iterator interface for an operator includes the functions open(), next(), and close(). The open() function initializes the state of the operator by allocating the appropriate input and output buffers and passing any related arguments. The code for the next() function calls the next() function recursively on each input operator until an output tuple is generated. The state of the operator keeps track of how much input has been consumed. Finally, when all output tuples have been produced, through repeated calls of the next() function, the close() function deallocates the state information and performs any other final bookkeeping.
By providing a common interface to all physical operators, any two physical operators can be plugged together. Furthermore, the iterator interface supports a pipeline model for the execution of the plan.
The iterator interface is also employed to encapsulate access methods such as the various kinds of indexes that the database system supports. In this case, open() can be used to pass the corresponding selection condition. Finally, parallelism and network communications can be encapsulated within special exchange iterators.