Should I create unique index if a column contains unique constraint and I want to fast search by this column?
For example I have a table users with column login that should be unique. I need fast search user by the login column.
Which is the best way to do it:
create a unique constraint (it creates internal unique index - is it used in select queries with WHERE login = 'something'?)
create a unique index
create a unique index and unique constraint (index duplicates internal index?)
Second case is unique login on not locked users (column locked = false). Postgres does not support partial conditions. Should I create a unique conditional and a partial index or is only a partial index enough?
And one more question: should I create new index for a column with a foreign key? For example: users.employee_id relates to employees.id, should I create an index on employee column for optimized query SELECT * FROM users WHERE employee_id = ....? When are internal indexes used by the optimization engine and when not?
I have a table 'users' with column login that should be unique
If this is the case you need a unique constraint. Unique constraints are enforced (behind the scenes) by unique indexes.
Conceptually:
The unique constraint defines the uniqueness.
The unique index implements the unique constraint.
The unique index provides speedy searches since it allows operations such as Index Range Scan and Index Seeks.
Is it used in select queries with WHERE login = 'something'?
Yes, it is.
Second case is unique login on not locked users (column locked = false).
If this is the case a unique constraint won't work. Maybe a trigger on insert could help here.
should I create new index for column with foreign key?
No, it's not needed (at least in the current version 10 and perhaps the later versions), s. documentation:
PostgreSQL automatically creates a unique index when a unique constraint or primary key is defined for a table. [...] There's no need to manually create indexes on unique columns; doing so would just duplicate the automatically-created index.
Related
One can specify the index while creating the primary key:
CREATE TABLE t (a NUMBER, b NUMBER);
ALTER TABLE t ADD PRIMARY KEY (a,b) USING INDEX (CREATE INDEX i ON t(a,b));
This works for column subsets, too:
ALTER TABLE t ADD PRIMARY KEY (a) USING INDEX (CREATE INDEX i ON t(a,b));
I prefer unique indexes (because a non-unique index adds the rowid to each key which makes the index bigger and slightly slower). This works, too:
ALTER TABLE t ADD PRIMARY KEY (a,b) USING INDEX (CREATE UNIQUE INDEX i ON t(a,b));
However, subset and unique index results in an error:
ALTER TABLE t ADD PRIMARY KEY (a) USING INDEX (CREATE UNIQUE INDEX u ON t(a,b));
ORA-14196: Specified index cannot be used to enforce the constraint.
To summarize:
OK PRIMARY KEY (a,b) USING INDEX ( INDEX(a,b) )
OK PRIMARY KEY (a,b) USING INDEX ( UNIQUE INDEX(a,b) )
OK PRIMARY KEY (a) USING INDEX ( INDEX(a,b) )
ERROR PRIMARY KEY (a) USING INDEX ( UNIQUE INDEX(a,b) )
I completely fail to understand why that is not possible.
I need it quite often, for instance for tables with two primary key columns (say country, city) and one further column (say population). As I always query the further column, a three column index would make sense. As the first two columns are unique (per primary key), the index will be unique as well, but Oracle won't let me do this. Why?
This is a comment that doesn't fit in the comments section, and it may be blatantly wrong.
My take is that Oracle can enforce the uniqueness of primary keys using either 1) a unique index or 2) a non-unique index (functioanality that may exist for historical reasons). Therefore:
Case #1: if it uses a unique index, all the heavy lifting of finding out if a value is unique is done by the index itself. It's part of its features.
Case #2: if it uses a non-unique index, the index is used to store the values, but the uniqueness is validated by the primary key constraint itself that scans the index for multiple values.
Now, your four examples fall into:
case #1 (non-unique)
case #2 (unique)
case #1 (non-unique)
not case #1, not case #2. This is why I think Oracle does not allow this one.
And of course, if anyone knows better, please correct me.
the unique index on the column (a,b) cannot be used to enforce a primary key on the column (a) and the database has rigthly prevented you doing this action.
This is because (1,100),(1,101),(1,102) are are legitimate values in the unique index on (a,b) where are enforcing that column a contains only 1,2,3,...etc cannot be actioned using the same index.
I have a table in Oracle 11g such as with below columns.
COL1_STATUS
COL2_ID
COL3_TYPE
COL4_DATE
I want to create a UNIQUE constraint combining all 4 columns but only when COL1_STATUS = 10
How can I do that? Table is already created so I am looking for only ALTER command.
Also, I have searched and found similar question where it is suggested to use unique index but I want to achieve this by constraint.
Conditional unique constraint with multiple fields in oracle db
Thanks in advance.
A unique index and a constraint are essentially the same thing. A unique constraint is implement using a unique index. So this really should do what you want:
create unique index idx_table_4 on
table(case when status = 10 then id end,
case when status = 10 then type end,
case when status = 10 then date end);
In fact, this is how the documentation recommends implementing a unique constraint:
When you specify a unique constraint on one or more columns, Oracle
implicitly creates an index on the unique key. If you are defining
uniqueness for purposes of query performance, then Oracle recommends
that you instead create the unique index explicitly using a CREATE
UNIQUE INDEX statement. You can also use the CREATE UNIQUE INDEX
statement to create a unique function-based index that defines a
conditional unique constraint. See "Using a Function-based Index to
Define Conditional Uniqueness: Example" for more information.
I have to insert data into a table that has a PK in it. I also have another table that has a clustered index in it.
Should I drop the PK or the INDEX for the the best INSERT speeds? Then recreate them afterwards?
I load data to these types of tables on a routine basis and I want to make sure I am using the quickest way possible in all situations.
A primary key uniquely identifies a record and has other uses as well. An index makes select queries run faster.
You should never drop your primary key.
Whether or not you drop and re-create indexes when adding records depends on the circumstances.
Primary Key : Uniquely identifies the the data & we cannot insert duplicate Data.
Index : Index help us to get out data to us very quickly.
Very Important Concept about Primary key & Index
Suppose your column is marked with the primary key then Clustered Index automatically gets created,
If no clutstered index is already present in the table
To See that Your Index is Created Successfully, You can use.
sp_helpindex Index_Name
- About Index :
You cannot create a unique index on a single column if that column contains NULL in more than one row. Similarly, you cannot create a unique index on multiple columns if the combination of columns contains NULL in more than one row. These are treated as duplicate values for indexing purposes.
- About Primary Key :
All columns defined within a PRIMARY KEY constraint must be defined as NOT NULL. If nullability is not specified, all columns participating in a PRIMARY KEY constraint have their nullability set to NOT NULL.
I'm trying to setup an indexed view on a table that doesn't have a unique id. It has two unique identifiers that if combined would be unique for it's row. I'm having trouble actually creating the unique clustered index that the indexed view requires when I found an thread on MSDN that folks all agree it is possible to create a unique clustered index out of 2 columns for a indexed view # http://social.msdn.microsoft.com/Forums/en/transactsql/thread/f2c99845-3af1-46e8-9b52-363c24988744
But for the life of me, can't figure out how to create it. I'm rolling with this query, but it doesn't seem to cut it.
CREATE UNIQUE CLUSTERED INDEX [PK] ON MyView
(
MyId1, MyId2
)
Error:
The CREATE UNIQUE INDEX statement terminated because a duplicate key
was found for the object name 'dbo.MyView' and the index name 'PK'.
The duplicate key value is (71cd9b68-1a9e-47bc-bc6b-0008b230a6d8,
0e64aa3a-0631-4caf-82d9-73609ee79b19).
The two IDs listed as duplicates are IDs from MyId2.
So, how could I create a unique clustered index here?
Well the error message seems to suggest that there is more than one record where MyId1 = 71cd9b68-1a9e-47bc-bc6b-0008b230a6d8 and MyId2 = 0e64aa3a-0631-4caf-82d9-73609ee79b19.
I would recommend running a query that selects based only on that criteria and confirming that this only returns one record. If it returns more, then you cannot recreate a UNIQUE constraint on these two columns unless you eliminate the duplicates.
In SQL Server 2005+ (I use both), does adding the UNIQUE constraint to a column automatically create an index, or should I still CREATE INDEX?
See this MSDN article:
The Database Engine automatically
creates a UNIQUE index to enforce the
uniqueness requirement of the UNIQUE
constraint.
If you do create an index, you'll end up with two indexes, as this example demonstrates:
create table TestTable (id int)
alter table TestTable add constraint unique_id unique (id)
create unique index ix_TestTable_id on TestTable (id)
select * from sys.indexes where [object_id] = object_id('TestTable')
This will display two unique indexes on TestTable; and the HEAP that represents the table itself.
Yes, it does.
In fact, you can even create a CLUSTERED UNIQUE CONSTRAINT:
ALTER TABLE mytable ADD CONSTRAINT UX_mytable_col1 UNIQUE CLUSTERED (col1)
, which will make the table to be clustered on col1.
Almost all databases create an index for UNIQUE CONSTRAINT, otherwise it would be very hard to maintain it.
Oracle doesn't even distinguish between UNIQUE CONSTRAINT and UNIQUE INDEX: one command is just a synonym for another.
The only difference in Oracle is that a UNIQUE INDEX should have a user-supplied name, while a UNIQUE CONSTRAINT may be created with a system-generated name:
ALTER TABLE mytable MODIFY col1 UNIQUE
This will create an index called SYS_CXXXXXX.
An index is created when you add a unique constraint:
Reference -- see the second paragraph.
When a UNIQUE constraint is added to
an existing column or columns in the
table, by default, the Database Engine
examines the existing data in the
columns to make sure all values are
unique. If a UNIQUE constraint is
added to a column that has duplicated
values, the Database Engine returns an
error and does not add the constraint.
The Database Engine automatically
creates a UNIQUE index to enforce the
uniqueness requirement of the UNIQUE
constraint. Therefore, if an attempt
to insert a duplicate row is made, the
Database Engine returns an error
message that states the UNIQUE
constraint has been violated and does
not add the row to the table. Unless a
clustered index is explicitly
specified, a unique, nonclustered
index is created by default to enforce
the UNIQUE constraint.