I am trying to create a FTS on table which has partitioning and row level security enabled on it.
As FTS requires a single-column unique index, I have added a new identity column , but not able to create unique index on it as it asks to add partitioning key which will end up in multiple column index.
So, I tried creating a view on top of my table --> and then adding single-column unique index to make it an indexed view. But now the problem is as I have RLS enabled on base table, it's not allowing me to create an indexed view. I can't remove RLS from my table. Is there any workaround for this?
Thanks!
Related
I'm using the Data Skipping Indexes feature in clickhouse and i got confused about its usage. If i add a data skip index when i create the table like this:
CREATE TABLE MyTable
(
...
INDEX index_time TimeStamp TYPE minmax GRANULARITY 1
)
ENGINE =MergeTree()
...
When i query with TimeStamp filter condition the 'index_time' works. But if i didn't add index when creating table, alternatively, i added the index with Manipulations With Data Skipping Indicesfeature like this:
ALTER TABLEE MyTable ADD INDEX index_time TimeStamp TYPE minmax GRANULARITY 1
Then the index 'index_time' doesn't work.
My database is running on production so i can't recreate the table. I have to use the second way. Can anyone explain why it does not work or i used the feature in a wrong way?
The reason your queries don't use the index after an ALTER TABLE ADD INDEX is because the index does not exist yet. (!)
Any new data will be properly indexed, which is why your index works when you put it in CREATE TABLE. ClickHouse builds the index as you load data. If you created the table, ran ALTER TABLE ADD INDEX, and loaded data you would see the same behavior.
When the data already exist, things are different. ALTER TABLE updates the metadata for the table, but at this point all your data have been written to parts in the table. ClickHouse does not rewrite parts automatically to implement new indexes. However, you should be able to force rewriting to include the index by running:
OPTIMIZE TABLE MyTable FINAL
See the Github issue https://github.com/yandex/ClickHouse/issues/6561 referenced by Ruijang for more information.
It's quite right that
OPTIMIZE TABLE my_table_name FINAL;
does recreate the indexes set to the table. But there's some scenarios in a columnar DB where you want to avoid rewriting EVERYTHING. If you just add a single index to an already existing table with lots of data when you just rebuilt the new index which includes two steps:
Step 1 - Define the index
Creating the INDEX itself just defines what the index should do, which reflects in Clickhouse as metadata that's added to the table. Thus there is no index build up really, thus nothing will be faster. It's also a lightweight operation as it won't change data or build up any structures beside the table metadata.
It's important to understand any new incoming data will be indexed on insert, but any pre existing data is not included!
ALTER TABLE my_table_name ADD INDEX my_index(my_expression) TYPE minmax GRANULARITY 1
Note Clickhouse can index expressions, so it could simply be the column name as in the question or a more complex expression (e.g. my_index(price * sold_items * revshare)). The index will work on that expression only of course.
Step 2 - Build up (materialize) the index
After creation of the metadata the index for existing data need to be build up. This action is called materialize and needs to be explicitly triggered. Good thing is you can do this individually for any index that was added or changed. This is a heavy operation as it'll trigger work on the database.
ALTER TABLE my_table_name MATERIALIZE INDEX my_index;
Also have a look at the Clickhouse docs for Manipulating Data Skipping Indices
I need to update the primary key of a large Index Organized Table (20 million rows) on Oracle 11g.
Is it possible to do this using multiple UPDATE queries? i.e. Many smaller UPDATEs of say 100,000 rows at a time. The problem is that one of these UPDATE batches could temporarily produce a duplicate primary key value (there would be no duplicates after all the UPDATEs have completed.)
So, I guess I'm asking is it somehow possible to temporarily disable the primary key constraint (but which is required for an IOT!) or alter the table temporarily some other way. I can have exclusive and offline access to this table.
The only solution I can see is to create a new table and when complete, drop the original table and rename the new table to the original table name.
Am I missing another possibility?
You can't disable / drop the primary key constraint from an IOT, since it is a unique index by definition.
When I need to change an IOT like this, I either do a CTAS (create table as) for a new plain heap table, do my maintenance, and then CTAS a new IOT.
Something like:
create table t_temp as select * from t_iot;
-- do maintenance
create table t_new_iot as select * from t_temp;
If, however, you need to simply add or join a new field to the existing key, you can do this in one step by creating the new IOT structure, then populating directly from the old IOT with a query.
Unfortunately, this is one of the downsides to IOTs.
I would recommend following method:
Create new IOT table partitioned by system with single partition
with exactly same structure as current one.
Lock current IOT table to prevent any DML.
insert into new table as select from current table changing PK values in select. This step
could be repeated several times if needed. In this case it's better
to do it in another session to keep lock on original table.
Exchange partition of new table with original table.
When i create a primary key in oracle table, why does it create a 'clustered' index by default. What is the reason for this automatic creation of a clustered index on creation of a primary key? is it just the Oracle designer's preference that he designed oracle in this way?
Oracle will create an index to police an unique constraint where no pre-existing index is suitable. Without the index, Oracle would need to serialize operations (such as a table lock) whenever someone tries to insert or delete a row (or update the PK).
Contrarily to MS-SQL Server, this index is not clustered on heap tables (default table organization), i.e. this index won't change the underlying table structure and natural order. The rows won't be reordered when Oracle creates the index. The index will be a B-tree index and will exist as a separate entity where each entry points to a row in the main table.
Oracle doesn't have clustered index as MS SQL, however indexed-organized tables share some properties with cluster-indexed tables. The PK is an integral part of such tables and has to be specified during creation.
(Oracle also has table clusters, but they are a completely different concept).
Creating Index is basic functionality of Primary key, it is also in SQL Server and MySQL, Clustered Index makes your searches faster.
The Database Engine automatically creates a unique index to enforce the uniqueness of the PRIMARY KEY constraint. If a clustered index does not already exist on the table or a nonclustered index is not explicitly specified, a unique, clustered index is created to enforce the PRIMARY KEY constraint.
Read this:
http://www.sqlskills.com/blogs/kimberly/the-clustered-index-debate-continues/
I understand I can't do this straightforward from studying similar questions on stackoverflow and other sites.
However, I need to do this and I'm willing to go with workarounds.
I tried to create a non-unique index with online and parallel, and then drop the old unique index. However, it fails saying ORA-01408: such column list already indexed.
How to convert an unique index to a non-unique one?
If you don't want to drop the old index before creating the new one, you can cheat a bit by creating the new index with an additional useless column, e.g.:
Assuming a table with the following configuration:
create table mytable (id number);
create unique index myunique on mytable (id);
To convert the index to non unique:
create index temp on mytable (id, 1);
drop index myunique;
create index mynonunique on mytable (id);
drop index temp;
In practice I'm not sure how necessary this is - generally I'd just drop and recreate the index in some low-activity period, preferably take the application down.
Oracle now supports multiple indexes applied to the same set of columns as long as they differ in uniqueness (and/or in some other properties such as bitmap vs. btree and partitioning) and
as long as only one of them is visible.
Therefore you can alter the existing index - changing it to invisible without dropping it and then create a new non-unique index.
CREATE TABLE mytable (id NUMBER);
CREATE UNIQUE INDEX mytable_unique_idx ON mytable(id);
ALTER INDEX mytable_unique_idx INVISIBLE;
CREATE INDEX mytable_nonunique_idx ON mytable(id);
Note that invisible indexes are still maintained by the database and you can change between them by turning one of them to invisible and the second one to visible.
I created a table and one of the columns is address. I then created a view with a WHERE CONTAINS clause that states select can only be performed on address that contain a specific word.
I then created an index of the address column on the original table.
It says index created.
When I type
select * from myview
It says
drg-10599: column is not indexed.
Any idea why this isn't working?
You would need to create an Oracle Text index, not a standard b-tree index. There are quite a few options for creating and maintaining Oracle Text indexes that you should really read through in order to figure out exactly what options you want to use.
The simplest possible DDL statement would be
CREATE INDEX myindex ON table_a(address)
INDEXTYPE IS CTXSYS.CONTEXT;