Create index in huge MariaDB production database without table locking - indexing

I have a table with 202M records where I need to add a few indexes and I can't find it anywhere (or maybe I don't understand the lingo) if that is possible to do, without locking, in MariaDB 10.3.
I found this post where I can see that that is possible in MySQL 5.6+, but my google foo didn't get my any info on MariaDB.
I tried using pt-online-schema-change but since I don't have any index (not even primary) that is not an option.

This is possible with the use of ALTER ONLINE TABLE.
ALTER ONLINE TABLE is equivalent to LOCK=NONE. Therefore, the ALTER
ONLINE TABLE statement can be used to ensure that your ALTER TABLE
operation allows all concurrent DML.
Further reading tells that adding primary keys is a "copy" operation as DB engine needs to copy the whole table to new file, but adding other indexes in an inplace operation.
InnoDB supports adding a primary key to a table with ALGORITHM set to
INPLACE. The table is rebuilt, which means that all of the data is
reorganized substantially, and the indexes are rebuilt. As a result,
the operation is quite expensive. This operation supports the
non-locking strategy. This strategy can be explicitly chosen by
setting the LOCK clause to NONE. When this strategy is used, all
concurrent DML is permitted.
InnoDB supports adding a plain index to a table with ALGORITHM set to
INPLACE. The table is not rebuilt. This operation supports the
non-locking strategy. This strategy can be explicitly chosen by
setting the LOCK clause to NONE. When this strategy is used, all
concurrent DML is permitted.
More info in MariaDB documentation.

Related

Run DB2 Runstats without activity but still get SQLSTATE=01650

After reading many of articles from the internet, I am still not sure what is the actual purpose of DB2 Runstats.
As my understanding, DB2 Runstats will "register" the table index to the DB2 catalog, so that next time when the related query run, it will use the index to increase the performance. (Please correct me if I am wrong)
Meaning, if for a long period of time the DB2 Runstats is not run, the index will be removed from the DB2 catalog?
I am creating a new index for a table. Originally that table already contained another index.
After creating the new index, I ran DB2 Runstats on the table for the old index, but I hit the following error:
SQL2314W Some statistics are in an inconsistent state. The newly collected
"INDEX" statistics are inconsistent with the existing "TABLE" statistics. SQLSTATE=01650
At first I was thinking it's cause by the activity to create the new index, and the table was still in the "processing" stage. I ran the DB2 Runstats command again the next day but still got the same error.
Your understanding about db2 runstats is not correct. This command collects statistics on the given table and its indexes and placed it to views in the SYSSTAT schema like SYSSTAT.TABLES, SYSSTAT.INDEXES, etc. This information is used by the DB2 optimizer to produce better access plans of your queries. It doesn't "register" indexes itself. Indexes are not removed automatically if you don't collect statistics on them.
As for the warning message SQL2314W.
It's just a warning that table and index statistics is not logically compatible (for example, number of index keys is more than number of rows in the table). Sometimes it happens when you collect statistics on actively updated table at the same time even you run such a collection on a table and its indexes using a single RUNSTATS command. You can either ignore this message or make the RUNSTATS utility lock the table during the statistics collection on table and its indexes using a single command (ALLOW READ ACCESS clause).

reinitialise transactional replication without dropping subscriber table 2008R2

Normally when we reinitialise transactional replication it drops the table on the subscriber and recreates it. I want to have a clustered PK on the source database with a non-clustered PK of the same column on the destination and a different clustered index. I understand I can achieve this by temporarily stopping the replication making the changes and enabling it again.
I'm more worried about the future if we ever need to reinitialise I don't want the table to be dropped and lose our different index strategy. I might be being blind but I can't find a setting to allow the table structure on the subscriber to be kept on reinitialisation.
I found the answer. You set this in the article properties of the replication. You can choose to truncate all data if the table already exists.

What is the most efficient way of creating a copy of a table with data and no constraints in Oracle?

What is the most efficient way of creating a copy of a table with data and no constraints (Primary key and foreign) in Oracle? some thing similar to the below query.
CREATE TABLE new_table
AS
SELECT * FROM old_table;
It's fine if we need to drop the constraints manually after copying but the creation of copy should be quick.
Please advise.
Using a CREATE TABLE AS SELECT statement the way you have it now is probably the most efficient way to do it. If not, it's pretty close.
It doesn't create constraints (apart from not null constraints) or indexes, so you have to create them manually after the operation completes.
You can specify that the operation should be parallelized by using the parallel keyword, though I believe that the feature is only available in the Enterprise Edition. Example:
create table new_table
parallel
as
select * from old_table;
It's even possible to specify the number of threads to use by adding an integer parameter right after the parallel keyword. But, by default, it parallelizes according to the available CPUs on the server.
It is also possible to make the operation even faster by avoiding redo log generation. This is done by specifying the nologging keyword:
create table new_table
parallel
nologging
as
select * from old_table;
However, because no redo log is generated, the operation is unrecoverable. So, if you're going to use that, you should consider backing up the database immediately after the operation completes. I would personally not use this option unless that extra performance is critical for some reason.
For more information on how to use the additional options with the create table as select statement, see the documentation: CREATE TABLE.

Is gathering statistics necessary after dropping indexes and recreating them?

I use Oracle SQL, and I have one question. I have a table with indexes and it's statistics are gathered. I have a procedure that drops the indexes, inserts data into the table, and after that recreates the same indexes again. Do I need to gather statistics again after this procedure, or will the indexes be recognized anyway?
For gathering statistics i use:
EXEC dbms_stats.gather_table_stats(''MIGBUFFER'','''||table_name||''',cascade=>TRUE);
No. There is no need to gather index statistics immediately after index creation, since Oracle automatically gathers stats for indexes at creation time.
From documentation,
Oracle Database now automatically collects statistics during index
creation and rebuild.
I think it was way back in earlier releases, when you could use COMPUTE STATISTICS clause to start or stop the collection of statistics on an index. But, now this clause has been deprecated. Oracle Database now automatically collects statistics during index creation and rebuild. This clause is supported for backward compatibility and will not cause errors.

sqlldr direct load=true with referential partition options

So I need to do multiple bulk inserts into a table with row level triggers. I thought it would be a good idea to gather the generated ids first, combine them with my data and then do a direct=true sql load. Normally this would work fine but the table is partitioned by reference so it cannot disable the foreign key constraint that would allow me to do the direct load.
Does anyone know of anyway around this? My first solution of bulk collecting into a varray and inserting every 100,000 went moderately fast but if I was able to do a direct load, that would be much faster.
ERROR: SQL*Loader-965: Error -1 disabling constraint client_fk on
table my_table
The manual implies there is no way to have SQL*Loader use a direct path load but not disable the foreign keys.
But direct-path inserts can work on reference partitioned tables, even with the foreign keys enabled, as I demonstrated in this question and answer.
Convert the process from SQL*Loader to an external table INSERT statement. SQL*Loader and external tables use similar mechanisms so the conversion shouldn't be too difficult. External tables require a little more work - you have to write the INSERT with an append hint, and manually disable and re-enable triggers and perhaps other objects. But that extra control allows loading data quickly with direct-path inserts.