Oracle SQL can't select my indexes - sql

I created indexes like this:
--CREATE INDEXES for Tables
CREATE UNIQUE INDEX worker_name_index ON WORKER (worker_id);
CREATE UNIQUE INDEX company_name_index ON COMPANY (company_name);
CREATE UNIQUE INDEX project_name_index ON PROJECT (project_id);
But cant find where the indexes are:
SELECT * FROM USER_INDEXES;
Also not here:
SELECT * FROM ALL_INDEXES;
nor here:
SELECT * FROM DBA_INDEXES;
And also cant drop these indexes, because dropping throws ORA-01418:specified index does not exist error.
--REMOVE INDEXES
DROP INDEX project_name_index;
DROP INDEX company_name_index;
DROP INDEX project_name_index;
and can't recreate, because creation rise ORA-01408:such columnt in list already indexed error...
Edited (with select * all_ind_columns and the index is not there)

Your question seems to be a little misleading as you won't ever have been able to successfully create those named indexes. As shown by your subsequent queries against all_ind_columns, such as:
select * from all_ind_columns
where table_name = 'WORKER' and column_name = 'WORKER_ID'
... system-generated indexes already exist for the columns you are trying to index. The names (e.g. SYS_C0011015) indicate that they are system-generated backing indexes for primary key (or possibly unique) constraints defined against the tables.
The documentation notes in several places:
If you do not specify a constraint name, then Oracle generates a
system name for the constraint of the form SYS_Cn.
So you can't have created the named indexes; if the constraints already existed on the tables then you'd always have got an ORA-01408, and if you'd tried to add the constraints after the indexes were created then the alter would have failed. Since they really don't exist it's quite reasonable that they aren't listed in all_indexes and cannnot be dropped, and you can't recreate them for the same reason you can't have created them in the first place...

Probably you created the index with a different oracle user than the user you use for dropping or selecting this index.

Related

Exclude NULL value from UNIQUE INDEX in HANA

I Need to create a Unique Index in HANA with nullable column. I need to exclude NULL value from Index.
In SQL SERVER I can create an Index with this sintax:
CREATE UNIQUE NONCLUSTERED INDEX [MyTableIX_] ON [dbo].[MyTable]
(
[MyField1] ASC,
[MyField2] ASC,
[MyField3] ASC
)
WHERE ([MyField1] IS NOT NULL AND [MyField2] IS NOT NULL AND [MyField3] IS NOT NULL)
How can obtain the same result in HANA?
AFAIK This is not possible as a UNIQUE index requires that all of the entries are unique at the time the index is created, and will prevent records being added which would create duplicate entires in the index. (The documentation explains this)
Most Database systems work this way- unique means unique.
However, if your table is a column store (most are in HANA) then do you really need to create this index? The Column store optimises the table for retrieval of data (which is why in HANA generally reads are so much faster than writes) so for retrieval the use of index may not make any significant difference.
If you want to enforce uniqueness you could implement a trigger on the table instead which would abort the insert or update if it finds any records which conflict.
The "Filtered Index" syntax for MS SQL Server is intended to optimised retrieval for a particular subset of records in the table so that when the filter applies an index can be used which does not have to cover all rows of the table - resulting in a shorter index and a (hopefully) faster query.
Given that for column store tables (most tables in HANA) every field is effectively indexed the need for optimised indexes for subsets of the table is reduced (probably to zero, depending on the data schema and values).

How to find references to a particular index?

How do I find all DB references (such az INDEX optimizer hints) to a particular index?
(I plan to drop an index, and need to know whether it has any dependant objects associated.)
Especially, This sql_text column of this sql may be helpful for an individual index :
select p.sql_id, q.sql_text, p.access_predicates
from gv$sql_plan p
inner join gv$sql q on ( p.sql_id = q.sql_id )
where p.object_name = upper('&i_index_name')
group by p.access_predicates, q.sql_text, p.sql_id
order by p.access_predicates, q.sql_text, p.sql_id;
An Index does not have any dependencies. An Index is based on table(s) and column(s). If you like to know whether an index was used by any query you can use Index Monitoring feature.
You can enable/disable monitoring by
ALTER INDEX my_index_i MONITORING USAGE;
ALTER INDEX my_index_i NOMONITORING USAGE;
Then you can check index usage in view v$object_usage(for release 12.1 and less) or dba_object_usage

Performance issues while DELETE operation

I have a simple delete statement like this:
DELETE FROM MY_TABLE WHERE ID='Something'
This deletes only one record for that ID, which is taking more than a minute since MY_TABLE is referenced by a Foreign Key created on another table that has around 40 millions records and the DELETE operation checks existence of this ID in that large table.
One way is to drop/re-create this Foreign Key, but this DELETE operation gets performed by the application users and I can not just drop/re-create this FK on the fly unless it could have been an off-hours operation.
Can anyone help?
So there's an excellent SO question that you can refer
SQL delete performance.
Apart from the suggestions on the question like
Possible causes:
1) cascading delete operations
2) trigger(s)
3) the type of your primary key column is something other than an
integer, thereby forcing a type conversion on each pk value to do the
comparison. this requires a full table scan.
4) does your query really end in a dot like you posted it in the
question? if so, the number may considered to be a floating point
number instead of an integer, thereby causing a type conversion
similar to 3)
5) your delete query is waiting for some other slow query to release a
lock
Importantly:
We should definitely look into triggers. You should try to do away with triggers if there are any.
Also try to see if there are index on the FK in the other large table.
See if you can convert your query to a CASCADE delete to deleting from large table and then deleting from the MY_TABLE like in query below
DELETE FROM LARGE_TABLE WHERE LT.FK IN (SELECT PK FROM MY_TABLE WHERE ID='Something')
GO
DELETE FROM MY_TABLE WHERE ID='Something'
Also see the performance plan for first query on LARGE_TABLE.
You should try to replace WHERE ID='Something' with an INT key operation like WHERE anotherID=34. Basically instead of using a string in WHERE try to use integers for deletion. It is hard to believe that ID column in varchar. You should have a Primary KEY clustered indexed column in MY_Table, and use this key in WHERE clause.
Another way to improve performance is to drop the FK contraint between tables. You can always periodically do garbage deletion from LARGE_TABLE followed by Index rebuilding.
Another simpler way is to introduce mapping table between these tables. Where say a table named Map_My_Table_Large_Table exists which keeps following columns (FK column from My_Table, FK column from Large_Table). You can shift your CASCADE delete to this table.

Decision when to create Index on table column in database?

I am not db guy. But I need to create tables and do CRUD operations on them. I get confused should I create the index on all columns by default
or not? Here is my understanding which I consider while creating index.
Index basically contains the memory location range ( starting memory location where first value is stored to end memory location where last value is
stored). So when we insert any value in table index for column needs to be updated as it has got one more value but update of column
value wont have any impact on index value. Right? So bottom line is when my column is used in join between two tables we should consider
creating index on column used in join but all other columns can be skipped because if we create index on them it will involve extra cost of
updating index value when new value is inserted in column.Right?
Consider this scenario where table mytable contains two three columns i.e col1,col2,col3. Now we fire this query
select col1,col2 from mytable
Now there are two cases here. In first case we create the index on col1 and col2. In second case we don't create any index.** As per my understanding
case 1 will be faster than case2 because in case 1 we oracle can quickly find column memory location. So here I have not used any join columns but
still index is helping here. So should I consider creating index here or not?**
What if in the same scenario above if we fire
select * from mytable
instead of
select col1,col2 from mytable
Will index help here?
Don't create Indexes in every column! It will slow things down on insert/delete/update operations.
As a simple reminder, you can create an index in columns that are common in WHERE, ORDER BY and GROUP BY clauses. You may consider adding an index in colums that are used to relate other tables (through a JOIN, for example)
Example:
SELECT col1,col2,col3 FROM my_table WHERE col2=1
Here, creating an index on col2 would help this query a lot.
Also, consider index selectivity. Simply put, create index on values that has a "big domain", i.e. Ids, names, etc. Don't create them on Male/Female columns.
but update of column value wont have any impact on index value. Right?
No. Updating an indexed column will have an impact. The Oracle 11g performance manual states that:
UPDATE statements that modify indexed columns and INSERT and DELETE
statements that modify indexed tables take longer than if there were
no index. Such SQL statements must modify data in indexes and data in
tables. They also create additional undo and redo.
So bottom line is when my column is used in join between two tables we should consider creating index on column used in join but all other columns can be skipped because if we create index on them it will involve extra cost of updating index value when new value is inserted in column. Right?
Not just Inserts but any other Data Manipulation Language statement.
Consider this scenario . . . Will index help here?
With regards to this last paragraph, why not build some test cases with representative data volumes so that you prove or disprove your assumptions about which columns you should index?
In the specific scenario you give, there is no WHERE clause, so a table scan is going to be used or the index scan will be used, but you're only dropping one column, so the performance might not be that different. In the second scenario, the index shouldn't be used, since it isn't covering and there is no WHERE clause. If there were a WHERE clause, the index could allow the filtering to reduce the number of rows which need to be looked up to get the missing column.
Oracle has a number of different tables, including heap or index organized tables.
If an index is covering, it is more likely to be used, especially when selective. But note that an index organized table is not better than a covering index on a heap when there are constraints in the WHERE clause and far fewer columns in the covering index than in the base table.
Creating indexes with more columns than are actually used only helps if they are more likely to make the index covering, but adding all the columns would be similar to an index organized table. Note that Oracle does not have the equivalent of SQL Server's INCLUDE (COLUMN) which can be used to make indexes more covering (it's effectively making an additional clustered index of only a subset of the columns - useful if you want an index to be unique but also add some data which you don't want to be considered in the uniqueness but helps to make it covering for more queries)
You need to look at your plans and then determine if indexes will help things. And then look at the plans afterwards to see if they made a difference.

No indexes found in any table - is that possible?

By executing the following command that will list out all indexes found in my schema, the query returned nothing - suggesting that either no index is created, or probably i do not have sufficient permission.
select * from user_indexes;
Are there any more ways to list the indexes i have in a schema?
Sure it's possible.
Common, even :)
It just means nobody's created any indexes.
If the query returned nothing, it means that you DO have permission ... and there simply aren't any indexes.
Here's a good link on "Managing indexes in Oracle" (it sounds like you're probably running Oracle):
http://download.oracle.com/docs/cd/B19306_01/server.102/b14231/indexes.htm
As paulsm4 say, you do not have any indexes in your schema.
you can use
select * from all_indexes;
and you'll see all your indexes + the others where you have rights.
Florin is correct, USER_INDEXES is a view on ALL_INDEXES that only shows those which were created by you. You can query ALL_INDEXES directly to determine if anyone else has created indexes on the table in question but you will probably want to add a where clause for the table_name as it will list all indexes for all tables in the instance and also only some of the columns.
SELECT TABLE_NAME, INDEX_NAME FROM ALL_INDEXES WHERE TABLE_NAME='XYZ';
You can limit which tables using an IN CLAUSE if there is are several tables you are interested in
SELECT TABLE_NAME, INDEX_NAME FROM ALL_INDEXES WHERE TABLE_NAME IN ('ABC','XYZ');
and you can use a like clause if there is a prefix or suffix
SELECT TABLE_NAME, INDEX_NAME FROM ALL_INDEXES WHERE TABLE_NAME like 'XYZ%';
Also, if you want to see which columns these indexes are on, you can select from ALL_IND_COLUMNS;
SELECT * FROM ALL_IND_COLUMNS WHERE TABLE_NAME='XYZ'
Note that whether a table has indexes or not depends on the data and the usage. A small lookup table that has maybe a hundred rows or less would not need an index whereas a table that contains millions of rows but is queried for just a handful when needed would need an index.