I have a table with columns id, name, created_at and severity and the table can end up having milions of records.
I am considering to apply indexing on created_at and severity as that is what I am filtering by on UI.
I also need to have composite primary key set on id and created_at
PRIMARY KEY, btree (created_at, id) [Due to some 3rd party tool requirements]
With the above primary key setup do I just need to add a simple index on severity (as created_at is already indexed) or should I create a composite index on [created_at, severity]
According to the docs, if you are going to be filtering on those two fields together, then it's advised that you should do a multicolumn index.
As shown in the docs, if you have a table:
CREATE TABLE test2 (
major int,
minor int,
name varchar
);
and query often with:
SELECT name FROM test2 WHERE major = constant AND minor = constant;
then it's a good idea to index like:
CREATE INDEX test2_mm_idx ON test2 (major, minor);
Related
I'm trying to create a foreign key between two tables. Problem is one of those tables has a composite primary key..
My tables are products (one row per product) and product_price_history (many rows per product).
I have a composite key in product_price_history, which is product id and start date of a specific price for that product.
Here's my code :
CREATE TABLE products (
product_id INT IDENTITY(1,1) PRIMARY KEY,
product_name VARCHAR(50) NOT NULL,
product_desc VARCHAR(255) NULL,
product_group_id INT
)
CREATE TABLE product_price_history (
product_id INT NOT NULL,
start_date DATE NOT NULL,
end_date DATE NULL,
price NUMERIC (6,2) NOT NULL
)
ALTER TABLE product_price_history
ADD CONSTRAINT pk_product_id_start_dt
PRIMARY KEY (product_id,start_date)
Now I'm trying to create a foreign key between the products table and the product_price_history table but I can't because its a composite key.
Also it doesn't make sense to add the start date (the other part of the foreign key) to the products table.
What's the best way to deal with this? Can I create a foreign key between these tables? Do I even NEED a foreign key?
My intentions here are
to enforce uniqueness of the product price information. A product can only have one price at any time.
to link these two tables so there's a logical join between them, and I can show this in a database diagram
The foreign key on the product_price_history table should only include product_id. Your target is to ensure that any entry product_price_history already has "parent" entry in products. That has nothing to do with start_date.
The way I see this situation, in theory, fully normalized version of the tables would have to have current_price as unique value in products table. And the product_price_history is simply a log table.
It's not necessary to do it this way, with a physical field, but thinking from this perspective helps to see where your tables model is slightly de-normalized.
Also, if you make product_price_history table anything but simple log table, how do you ensure that new start_date is newer than previous end_date? You can't even express that as a primary key. What if you edit start_date later? I would even think to create different compaund key for product_price_history table. Perhaps product_id+insert_date or only auto-increment id, while still keeping foreign key relationship to the products.product_id.
I created table in Cassandra database name as information_tbl.
query:
CREATE TABLE IF NOT EXISTS Information_tbl (id uuid ,
cam_id varchar,
camzone varchar,
msg varchar,
fltr int,
time_stamp int,
PRIMARY KEY (fltr,time_stamp)
)WITH CLUSTERING ORDER BY (time_stamp DESC);
when I execute update query, it show error :
Query 1:
UPDATE information_tbl SET camzone = 'D' WHERE id = c6263cac-450f-4105-a2cc-3705ec741a96;
Error:
message="Some partition key parts are missing: fltr"
Query 2:
UPDATE information_tbl SET camzone = 'D' WHERE fltr=1 AND id = c6263cac-450f-4105-a2cc-3705ec741a96;
Error:
message="Some clustering keys are missing: time_stamp"
Query 3:
UPDATE information_tbl SET camzone = 'D' WHERE fltr=1 AND time_stamp = 1581946832 AND id = c6263cac-450f-4105-a2cc-3705ec741a96;
Error:
message="Non PRIMARY KEY columns found in where clause: id "
Any suggestions.
In the 3 queries provided, you are treating the column id as if it was part of the primary key; here is a succinct explanation of their characteristic. You may also visit the data model explanations in DS201 of DataStax Academy.
From the query example 2, it looks that fltr may have a low cardinality, which will also be troublesome, please refer to this explanation.
To update Cassandra row in Cassandra, you need Partition Key + Clustering Key. Coming to you error messages
Error 1 : message="Some partition key parts are missing: fltr" in this case you are not passing any partition key columns.
Error 2 : message="Some clustering keys are missing: time_stamp" in this case you are passing a part of partition key columns.
Error 3 : message="Non PRIMARY KEY columns found in where clause: id " in this case you are passing partition key columns along with other columns.
If you have the value of ID available, you can change your data model as below to perform an update.
CREATE TABLE IF NOT EXISTS Information_tbl (id uuid ,
cam_id varchar,
camzone varchar,
msg varchar,
fltr int,
time_stamp int,
PRIMARY KEY (id, fltr,time_stamp)
)WITH CLUSTERING ORDER BY (time_stamp DESC);
If you want to update table fields you must need primary key in where clouse for that.
If you do not have it first get it(primary key field value) using select query(you can use select query without primary key) and then use update query on the basis of that primary key.
I have a database in which i have two tables:
CREATE TABLE Transactions (
ID BIGINT IDENTITY(1,1) NOT NULL,
AccountID BIGINT NOT NULL,
Amount BIGINT NOT NULL,
CONSTRAINT PK_Transactions PRIMARY KEY CLUSTERED (ID ASC,AccountID ASC),
CONSTRAINT FK_Transaction_Account FOREIGN KEY (AccountID) REFERENCES Accounts(ID)
);
CREATE TABLE Accounts (
ID BIGINT IDENTITY(1,11) NOT NULL,
Balance BIGINT NOT NULL,
CONSTRAINT PK_Accounts PRIMARY KEY (ID)
);
Transactions are inserted to their table by a stored procedure i wrote, so that two rows are generated when Account 1 transfers 25 "coins" to Account 21:
ID | AccountID | Amount
-------------------------
1 | 1 | -25
-------------------------
1 | 21 | 25
In the above schema, i want the first row to reference the bottom row based on ID and the AccountID being unequal to the AccountID of the bottom row.
And vica versa.
What i want to do would look something like this:
CONSTRAINT FK_Transaction_Counterpart FOREIGN KEY (ID) REFERENCES Transactions(ID) WHERE thisRow.AccountID != referencedRow.AccountID
I haven't found this possibility in the documentation on the table constraints.
So both out of curiosity and intent to use this i ask, is this possible? And if yes, how?
Edit:
Answers reflect that this is not possible, and i should adjust my design or intentions.
I think i will settle with assigning the two transaction rows to each other in the functional code.
A traditional foreign key can't be conditional (i.e. no WHERE clause attached). In your case, I'd probably just make sure that the inserts are atomic (in the same transaction) so that there'd be no possibility of only one of them inserting.
If the data model you are trying to implement is:
One transaction (ID) has two and only two entries in table Transactions
For the two rows of a given Transaction ID, the AccountIDs cannot be the same
Then one perhaps overly-complex way you could enforce this business rule within the database table structures would be as follows:
Table Accounts, as you have defined
Table Transactions, as you have defined
New table TransactionPair with:
Columns (all are NOT NULL)
ID
LowAccountID
HighAccountID
Constraints
Primary key on ID (only one entry per Transaction ID)
Foreign key on (ID, LowAccountID) into Transactions
Foreign key on (ID, HighAccountID) into Transactions
Check constraint on the row such that LowAccountID < HighAccountID
Process:
Add pair of rows to Transactions table
Add single row to TransactionPair referencing the rows just added
If that row cannot be added, something failed, roll everything back
Seems neat and tidy, but quite possibly overly complex. Your mileage may vary.
Consider the following:
tbl_Book
BookID PK int identity(1,1)
tbl_Author
AuthorID PK int identity(1,1)
tbl_BookAuthor
BookID FK int
AuthorID FK int
I have a composite/compound primary key on (BookID, AuthorID). More specifically, default values based on SSMS designer:
Columns: (BookID ASC, AuthorID ASC)
Is Unique: Yes
Type: Primary Key
Create As Clustered: Yes
At any point, would I need a non-clustered index on any one of the columns (BookID, AuthorID) or is it not relevant when it's only and will always be only those two columns in the table, as a composite key.
If the only queries that run against this table specify both values of the composite key (or just the first value), then you need no other indexes. The only time I can think you might want another index is if you had queries on just the second column in the compound key (and couldn't make that the first column because you also had queries on just that column as well).
Short answer: things should be fine as-is.
Most likely a search on BookID would be an index seek
A search on AuthorID (without BookID) would be an index scan
If you are never going to search on just the second then it would not matter
It seems like a search on Author only would be more likely so I would switch that order.
I have a composite table called TeacherClass with two columns, TeacherID and ClassID. The primary key is both the TeacherID and ClassID. Even though these are also considered foreign keys, should I add an index to each column separately even though they have one on both of them combined from the primary key?
If you have a primary key on (TeacherID, ClassID), you already have an index on those two.
However, a query that uses only ClassID as its parameter won't be able to take advantage of that index - that index only works for (TeacherID) or (TeacherID, ClassID).
So yes - if you ClassID column is used as a foreign key into other tables, I would definitely argue you should put an index on just (ClassID).
An index on just TeacherID however is totally superfluous.
If they are both part of the PK, then most likely are already in a clustered index, but index will have, say (TeacherID, ClassID), not the other way around (ClassID, TeacherID). This means the table will be fast when running something like:
SELECT * FROM TeacherClass WHERE TeacherID = 9
But slow when running
SELECT * FROM TeacherClass WHERE ClassID = 9
If you are planning on running similar select statements, add a new index including ClassID and TeacherID, in that order. You won't need any separate indexes then (having an index that includes Col1 and Col2, makes an index that includes just Col1 redundant).