Error while dropping column from a table with secondary index (Scylladb) - scylla

While dropping a column from a table that contains secondary index I get the following error. I am using ScyllaDB version 3.0.4.
[Invalid query] message="Cannot drop column name on base table warehouse.myuser with materialized views"
Below are the example commands
create table myuser (id int primary key, name text, email text);
create index on myuser(email);
alter table myuser drop name;
I can successfully run the above statements in Apache Cassandra.

Default secondary indexes in Scylla are global and implemented on top of materialized views (as opposed to Apache Cassandra's local indexing implementation), which gives them new possibilities, but also adds certain restrictions. Dropping a column from a table with materialized views is a complex operation, especially if the target column is selected by one of the views or its liveness can affect view row liveness. In order to avoid these problems, dropping a column is unconditionally not possible when there are materialized views attached to a table. The error you see is a combination of that and the fact that Scylla's index uses a materialized view underneath to store corresponding base keys for each row.
The obvious workaround is to drop the index first, then drop the column and recreate the index, but that of course takes time and resources.
However, in some cases columns can be allowed to be dropped from the base table even if it has materialized views, especially if the column is not selected in the view and its liveness does not have any impact on view rows. For reference, I created an issue that requests implementing it in our bug tracker: https://github.com/scylladb/scylla/issues/4448

Related

Create materialised view without primary key column

Is it possible to create materialised view without using one of the primary key.
Use Case:-
I have a table with two primary keys, user_id and app_id, I want to create view to fetch data on the basis of app_id regardless of user_id. I am trying to create materialised view but Cassandra is not allowing me to do so if I keep only one primary key.
I know the fact that, I can use "allow filtering" but this will not give 100% accuracy in data.
In Cassandra, materialized view should always include all existing primary key components, but they could be in the different order. So in this case, you can create MV with primary key of app_id, user_id, but this may lead to big partitions if you have very popular application.
But I suggest just to create a second table with necessary primary key, and populate it from your application - it could be even more performant than having materialized view, because it needs to read data from disk every time you insert/update/delete record in the main table. Plus, take into account that materialized views in Cassandra are experimental feature, and have quite a lot of problems.

Creating Oracle tables with foreign keys that reference primary keys on materialized views

I have several materialized views in Oracle which I can query to get information.
Now I want to create several tables with foreign keys referencing those MVs and to do so, I have already "added" the corresponding primary keys to the MVs (as stated in adding primary key to sql view).
Then, when I execute my SQL create table query, I get an Oracle (ORA-02270) error: no matching unique or primary key for this column-list error at position 0, right at the beginning...
Am I doing something wrong? Is it possible what I am trying to do?
If not, how is it usually done?
When there are materialized views referenced by other tables' foreign keys, you have to take note on your views refresh method and how it affects your foreign keys.
Two things may prevent you from refreshing your materialized views:
1) The data in the tables referencing your views may reference lines that need to be updated or deleted. In that case you have to fix your data.
2) Your views' refresh method is complete. In complete refresh Oracle deletes all data in your mviews tables and repopulates them by rerunning their queries as you can see in Oracle site documentation - Refresh Types, while in fast refresh only the differences are applied to your mviews tables. Fast refresh is an incremental refresh and it won't work only if your foreign keys aren't respected by your data.
Now if there are mviews that can't be created with fast refresh (what Oracle calls them "Complex queries") then you can alter constraints to these mviews to deferrable as you can see here.
That way even complete refresh will work because Oracle only validates deferrable constraints by the end of current transaction. Therefore, as long as your refresh method is atomic, Oracle will issue an DELETE and than INSERT all rows back, all in one transaction.
In other words, in the next command to refresh your mview keep parameter atomic_refresh as true:
dbms_mview.refresh(LIST=>'MVIEW', METHOD =>'C', ATOMIC_REFRESH => TRUE);
By the way, this parameter's default value is TRUE, so just don't mention it and it will work.
The documentation states that:
View Constraints
Oracle does not enforce view constraints. However, operations on
views are subject to the integrity constraints defined on the
underlying base tables. This means that you can enforce constraints on
views through constraints on base tables.
and also:
View constraints are a subset of table constraints and are subject to
the following restrictions:
...
View constraints are supported only in DISABLE NOVALIDATE mode. You cannot specify any other mode. You must specify the keyword DISABLE
when you declare the view constraint. You need not specify NOVALIDATE
explicitly, as it is the default.
...
In practice, the above means that although constrains on views can be created, they are blocked and do not work. So as if they were not at all.
Apart from this, think for a moment what sense it would have foreign key constrainst created on tables, that would refer to a materialized view:
tables are always "online" and have always "fresh" data
materialized views can contain stale data
Imagine this case: You insert a record X into some table. This record is not visible in the materialized view yet, because the view is not refreshed at this moment. Then you try to insert record X into another table that has a foreign key constraint pointing to that materialized view. What the database should do ? Should the database reject the insert statement (since for now X is not visible yet in the view and the foreign key exists) ? If yes, then what about data integrity ? Mayby should it block amd wait until the view is refreshed ? Should it force the view to start refreshing or not in such a case?
As you can see, such a case involves many questions and difficult problems in the implementation, so Oracle simply does not allow for constrains on views.

Update Query Timeout on SQL Server View with MS Access

I am having some trouble with updates to an SQL Server View through MS Access. The set of tables used for this is built off of a base table. This base table is of this format.
Id int (not-nullable; auto-assigned)
A1 varchar(50) (nullable)
A2 varchar(50) (nullable)
B1 varchar(50) (nullable)
B2 varchar(50) (nullable)
C1 varchar(50) (nullable)
C2 varchar(50) (nullable)
One row on this table is updated by multiple groups of users in our company. For instance, user group "A" updates columns "A1" and "A2", user group "B" updates columns "B1" and "B2", and so forth. However, we also want to prevent user group "A" from updating the columns of user group "B". To accomplish this, I set up a view containing the columns appropriate for each user group. For instance, the view for user group "A" would only contain the columns "Id", "A1", and "A2". Then I set the "Bind To Schema" option on the views in SSMS to "Yes", and I set up a unique, clustered index on the "Id" column on each of the views. In MS Access, I connect to these views as linked tables using an ODBC connection. When I open the tables in MS Access in design view and check the indexes, it does properly identify the "Id" column as the primary key.
Here is where the trouble comes in: When I try to update a record through MS Access in one of the views, sometimes the update runs instantly, but sometimes the update times out. Here is the error that I get.
"SM_Notes_Bridge" is the actual name of one of my views. Almost all previous answers that I can find online say to increase the amount of time before the update times out in MS Access, which seems like it is not a solution for my problem as the update either runs instantly or times out. There is no middle ground.
Another note is that I am currently the only one using this base table and these views. Also, important systems are developed around that base table structure, so changing its structure will take a lot of convincing.
By creating an unique index on a schema bound view, you're creating an indexed view, also called a materialized view.
A relevant property of indexed views:
When executing DML on a table referenced by a large number of indexed views, or fewer but very complex indexed views, those referenced indexed views will have to be updated as well. As a result, DML query performance can degrade significantly, or in some cases, a query plan cannot even be produced (MSDN).
Thus, creating multiple indexed views on a table that is updated often is a big no-no! Review this MSDN page for further explanation when and when not to use an indexed view. Every insert and update will have to propagate to all the indexed views, and will cause locks on those views as well.
Drop the indexes on ALL views on that table. As far as you've told me, there's no reason at all to use indexed views and they will hurt performance in a major way when executing updates. Even if that didn't fix this issue, it will improve performance.

What happens to indexes when using ALTER SCHEMA to transfer a table?

I have a massive job that runs nightly, and to have a smaller impact on the DB it runs on a table in a different schema (EmptySchema) that isn't in general use, and is then swapped out to the usual location (UsualSchema) using
ALTER SCHEMA TempSchema TRANSFER UsualSchema.BigTable
ALTER SCHEMA UsualSchema TRANSFER EmptySchema.BigTable
ALTER SCHEMA EmptySchema TRANSFER TempSchema.BigTable
Which effectively swaps the two tables.
However, I then need to set up indexes on the UsualSchema table. Can I do this by disabling them on the UsualSchema table and then re-enabling them once the swap has taken place? Or do I have to create them each time on the swapped out table? Or have duplicate indexes in both places and disable/enable them as necessary (leading to duplicates in source control, so not ideal)? Is there a better way of doing it?
There's one clustered index and five non-clustered indexes.
Thanks.
Indexes, including those that support constraints, are transferred by ALTER SCHEMA, so you can have them in both the source and target object schema.
Constraint names are schema-scoped based on the table schema and other indexes names are scoped by the table/view itself. It is therefore possible to have identical index names in the same schema but on different tables. Constraint names must be unique within the schema.

Sql Server: altering a view makes clustered and full-text search indexes to be deleted

Scenario
I have got two tables: tblA and tblB, with the same structure. Every moment, one of them is online, and the other one is in stand by. Periodically data are updated in the stand by table, it goes online and the other one goes in stand by.
This procedure cannot be modified.
There is a trivial view that accesses the tables. Let's say vw:
create view vw as
select * from tblA
go
When the tables switch, the view is altered:
alter view vw as
select * from tblB
go
Issue
Now I have to create a full-text index on the view. No problem in creating the index.
But when I alter the view, the index is deleted.
I figure out that I have to recreate the full-text index every time I alter the table. But I wonder whether another solution exists.
This happens to all views, including standard indexed views. It is annoying.
From ALTER VIEW docs
ALTER VIEW can be applied to indexed views; however, ALTER VIEW unconditionally drops all indexes on the view.
No workaround exists: you have to recreate the view index or index the base table.