Author: elilevine Date: Wed Aug 27 18:26:23 2014 New Revision: 1620952 URL: http://svn.apache.org/r1620952 Log: Update multi-tenancy docs for PHOENIX-1204
Modified: phoenix/site/publish/multi-tenancy.html phoenix/site/source/src/site/markdown/multi-tenancy.md Modified: phoenix/site/publish/multi-tenancy.html URL: http://svn.apache.org/viewvc/phoenix/site/publish/multi-tenancy.html?rev=1620952&r1=1620951&r2=1620952&view=diff ============================================================================== --- phoenix/site/publish/multi-tenancy.html (original) +++ phoenix/site/publish/multi-tenancy.html Wed Aug 27 18:26:23 2014 @@ -1,7 +1,7 @@ <!DOCTYPE html> <!-- - Generated by Apache Maven Doxia at 2014-08-18 + Generated by Apache Maven Doxia at 2014-08-26 Rendered using Reflow Maven Skin 1.1.0 (http://andriusvelykis.github.io/reflow-maven-skin) --> <html xml:lang="en" lang="en"> @@ -124,30 +124,34 @@ <div class="page-header"> <h1>Multi tenancy</h1> </div> -<p>Support for multi-tenancy is built on top of the concepts of a <a href="views.html">VIEW</a> in Phoenix. Users create a logical tenant-specific table as a VIEW and query and update it just like with regular Phoenix tables. Data in these tenant-specific tables resides in a shared, regular Phoenix table (and thus in a shared HBase table) that is declared at table creation time to support multi-tenancy. All tenant-specific Phoenix tables whose data resides in the same physical HBase table have the same primary key structure but each tenantâs table can contain any number of non-PK columns unique to it. The main advantages afforded by this feature are:</p> -<ol style="list-style-type: decimal"> - <li>It implements physical tenant data isolation, including automatically constraining tenants to only work with data that âbelongsâ to the each tenant.</li> - <li>It prevents a proliferation of HBase tables, minimizing operational complexity.</li> -</ol> <div class="section"> <div class="section"> + <h3 id="Highlights">Highlights</h3> + <ul> + <li>Multi-tenancy in Phoenix works via a combination of multi-tenant tables and tenant-specific connections (detailed below).</li> + <li>Tenants open tenant-specific connections to Phoenix. These connections can only access data that belongs to the tenant.</li> + <li>Tenants only see their own data in multi-tenant tables and can see all data in regular tables.</li> + <li>In order to add their own columns, tenants create tanant-specific views on top of multi-tenant tables and add their own columns to the views.</li> + </ul> + </div> + <div class="section"> <h3 id="Multi-tenant_tables">Multi-tenant tables</h3> - <p>The first primary key column of the physical multi-tenant table must be used to identify the tenant. For example:</p> + <p>Multi-tenant tables in Phoenix are regular tables that are declared using the MULTI_TENANT=true DDL property. They work in conjuntion with tenant-specific connections (detailed below) to ensure that tenats only see their data in such tables. The first primary key column of multi-tenant tables identifies the tenant. For example:</p> <div class="source"> <pre>CREATE TABLE base.event (tenant_id VARCHAR, event_type CHAR(1), created_date DATE, event_id BIGINT) MULTI_TENANT=true; </pre> </div> - <p>In this case, the tenant_id column identifies the tenant and the table is declared to be multi-tenant. The column that identifies the tenant may be given any name, but must of type VARCHAR or CHAR.</p> + <p>The column that identifies the tenant may be given any name, but must of type VARCHAR or CHAR. Regular Phoenix connections work with such tables with no constraints, including working with data across tenant boundaries.</p> </div> <div class="section"> - <h3 id="Tenant-specific_Tables">Tenant-specific Tables</h3> - <p>Tenants are identified by the presence or absence of a TenantId property at JDBC connection-time. A connection with a non-null TenantId is considered a tenant-specific connection. A connection with an unspecified or null TenantId is a regular connection. A tenant specific connection may only query:</p> + <h3 id="Tenant-specific_Connections">Tenant-specific Connections</h3> + <p>Tenants are identified by the presence or absence of the TenantId property at JDBC connection-time. A connection with a non-null TenantId is considered a tenant-specific connection. A connection with an unspecified or null TenantId is a regular connection. A tenant-specific connection may only query:</p> <ul> - <li><b>their own schema</b>, which is to say it only sees tenant-specific views that were created by that tenant.</li> - <li><b>non multi-tenant global tables</b>, that is tables created with a regular connection without the MULTI_TENANT=TRUE declaration.</li> + <li><b>all data in non-multi-tenant (global) tables</b>, that is tables created with a regular connection without the MULTI_TENANT=true declaration.</li> + <li><b>their own data in multi-tenant tables</b>.</li> + <li><b>their own schema</b>, which is to say it only sees tenant-specific views that were created by that tenant (detailed below).</li> </ul> - <p>Tenant-specific views may only be created using a tenant-specific connection and the base table must be a multi-tenant table. Regular connections are used to create global tables, including those that can be used as base tables for tenant-specific tables.</p> <p>For example, a tenant-specific connection is established like this:</p> <div class="source"> <pre>Properties props = new Properties(); @@ -155,13 +159,15 @@ props.setProperty("TenantId", Connection conn = DriverManager.getConnection("localhost", props); </pre> </div> - <p>through which a tenant-specific table may be defined like this:</p> + </div> + <div class="section"> + <h3 id="Tenant-specific_Views_optional">Tenant-specific Views (optional)</h3> + <p>Tenant-specific views may only be created using tenant-specific connections. They are created the same way as views. The base table must be a multi-tenant table or another view that eventually points to one:</p> <div class="source"> <pre>CREATE VIEW acme.event AS SELECT * FROM base.event; </pre> </div> - <p>The tenant_id column is neither visible nor accessible to a tenant-specific view. Any reference to it will cause a ColumnNotFoundException.</p> <p>Alternately, a WHERE clause may be specified to further constrain the data as well:</p> <div class="source"> <pre>CREATE VIEW acme.login_event AS @@ -169,11 +175,11 @@ SELECT * FROM base.event WHERE event_type='L'; </pre> </div> - <p>Just like any other Phoenix view, whether or not this view is updatable is based on the rules explained <a href="views.html#Updatable_Views">here</a>. In addition, indexes may be added to tenant-specific tables just like with regular tables.</p> + <p>The tenant_id column is neither visible nor accessible to a tenant-specific view. Any reference to it will cause a ColumnNotFoundException. Just like any other Phoenix view, whether or not this view is updatable is based on the rules explained <a href="views.html#Updatable_Views">here</a>. In addition, indexes may be added to tenant-specific views just like to regular tables and views.</p> </div> <div class="section"> <h3 id="Tenant_Data_Isolation">Tenant Data Isolation</h3> - <p>Any DML or query that is performed on a tenant-specific table is automatically constrained to only operate on the tenantâs data. For the upsert operation, this means that Phoenix automatically populates the tenantId column with the tenantâs id specified at connection-time. For querying and delete, a where clause is transparently added to constrain the operations to only see data belonging to the current tenant.</p> + <p>Any DML or query that is performed on multi-tenant tables using a tenant-specific connections is automatically constrained to only operate on the tenantâs data. For the upsert operation, this means that Phoenix automatically populates the tenantId column with the tenantâs id specified at connection-time. For querying and delete, a where clause is transparently added to constrain the operations to only see data belonging to the current tenant.</p> </div> </div> </div> Modified: phoenix/site/source/src/site/markdown/multi-tenancy.md URL: http://svn.apache.org/viewvc/phoenix/site/source/src/site/markdown/multi-tenancy.md?rev=1620952&r1=1620951&r2=1620952&view=diff ============================================================================== --- phoenix/site/source/src/site/markdown/multi-tenancy.md (original) +++ phoenix/site/source/src/site/markdown/multi-tenancy.md Wed Aug 27 18:26:23 2014 @@ -1,25 +1,25 @@ # Multi tenancy -Support for multi-tenancy is built on top of the concepts of a [VIEW](views.html) in Phoenix. Users create a logical tenant-specific table as a VIEW and query and update it just like with regular Phoenix tables. Data in these tenant-specific tables resides in a shared, regular Phoenix table (and thus in a shared HBase table) that is declared at table creation time to support multi-tenancy. All tenant-specific Phoenix tables whose data resides in the same physical HBase table have the same primary key structure but each tenantâs table can contain any number of non-PK columns unique to it. The main advantages afforded by this feature are: - -1. It implements physical tenant data isolation, including automatically constraining tenants to only work with data that âbelongsâ to the each tenant. -2. It prevents a proliferation of HBase tables, minimizing operational complexity. +### Highlights +* Multi-tenancy in Phoenix works via a combination of multi-tenant tables and tenant-specific connections (detailed below). +* Tenants open tenant-specific connections to Phoenix. These connections can only access data that belongs to the tenant. +* Tenants only see their own data in multi-tenant tables and can see all data in regular tables. +* In order to add their own columns, tenants create tanant-specific views on top of multi-tenant tables and add their own columns to the views. ### Multi-tenant tables -The first primary key column of the physical multi-tenant table must be used to identify the tenant. For example: +Multi-tenant tables in Phoenix are regular tables that are declared using the MULTI_TENANT=true DDL property. They work in conjuntion with tenant-specific connections (detailed below) to ensure that tenats only see their data in such tables. The first primary key column of multi-tenant tables identifies the tenant. For example: CREATE TABLE base.event (tenant_id VARCHAR, event_type CHAR(1), created_date DATE, event_id BIGINT) MULTI_TENANT=true; -In this case, the tenant_id column identifies the tenant and the table is declared to be multi-tenant. The column that identifies the tenant may be given any name, but must of type VARCHAR or CHAR. - -### Tenant-specific Tables -Tenants are identified by the presence or absence of a TenantId property at JDBC connection-time. A connection with a non-null TenantId is considered a tenant-specific connection. A connection with an unspecified or null TenantId is a regular connection. A tenant specific connection may only query: +The column that identifies the tenant may be given any name, but must of type VARCHAR or CHAR. Regular Phoenix connections work with such tables with no constraints, including working with data across tenant boundaries. -* **their own schema**, which is to say it only sees tenant-specific views that were created by that tenant. -* **non multi-tenant global tables**, that is tables created with a regular connection without the MULTI_TENANT=TRUE declaration. +### Tenant-specific Connections +Tenants are identified by the presence or absence of the TenantId property at JDBC connection-time. A connection with a non-null TenantId is considered a tenant-specific connection. A connection with an unspecified or null TenantId is a regular connection. A tenant-specific connection may only query: -Tenant-specific views may only be created using a tenant-specific connection and the base table must be a multi-tenant table. Regular connections are used to create global tables, including those that can be used as base tables for tenant-specific tables. +* **all data in non-multi-tenant (global) tables**, that is tables created with a regular connection without the MULTI_TENANT=true declaration. +* **their own data in multi-tenant tables**. +* **their own schema**, which is to say it only sees tenant-specific views that were created by that tenant (detailed below). For example, a tenant-specific connection is established like this: @@ -27,20 +27,19 @@ For example, a tenant-specific connectio props.setProperty("TenantId", "Acme"); Connection conn = DriverManager.getConnection("localhost", props); -through which a tenant-specific table may be defined like this: +### Tenant-specific Views (optional) +Tenant-specific views may only be created using tenant-specific connections. They are created the same way as views. The base table must be a multi-tenant table or another view that eventually points to one: CREATE VIEW acme.event AS SELECT * FROM base.event; -The tenant_id column is neither visible nor accessible to a tenant-specific view. Any reference to it will cause a ColumnNotFoundException. - Alternately, a WHERE clause may be specified to further constrain the data as well: CREATE VIEW acme.login_event AS SELECT * FROM base.event WHERE event_type='L'; -Just like any other Phoenix view, whether or not this view is updatable is based on the rules explained [here](views.html#Updatable_Views). In addition, indexes may be added to tenant-specific tables just like with regular tables. +The tenant_id column is neither visible nor accessible to a tenant-specific view. Any reference to it will cause a ColumnNotFoundException. Just like any other Phoenix view, whether or not this view is updatable is based on the rules explained [here](views.html#Updatable_Views). In addition, indexes may be added to tenant-specific views just like to regular tables and views. ### Tenant Data Isolation -Any DML or query that is performed on a tenant-specific table is automatically constrained to only operate on the tenantâs data. For the upsert operation, this means that Phoenix automatically populates the tenantId column with the tenantâs id specified at connection-time. For querying and delete, a where clause is transparently added to constrain the operations to only see data belonging to the current tenant. +Any DML or query that is performed on multi-tenant tables using a tenant-specific connections is automatically constrained to only operate on the tenantâs data. For the upsert operation, this means that Phoenix automatically populates the tenantId column with the tenantâs id specified at connection-time. For querying and delete, a where clause is transparently added to constrain the operations to only see data belonging to the current tenant.