views:

198

answers:

9

We have an Oracle database here that's been around for about 10 years. It's passed through a lot of hands. In the course of those years, it's grown quite large, and there are some interesting anomalies in its design that have me perplexed.

Now, I'm historically a SQL Server developer. I used to steam and fume about the differences between The Microsoft Way(tm) and The Oracle Way(R). Now, I realize, they're just different. I also used to yank my hair out and slam my head against the desk thinking that the people who came before me were blind, deaf mutes jacked up on Jolt and Red Bull, who wrote code in Tourette's.NET.

(Yes, I'm going somewhere.)

As time passed, I realized that neither database platform was inherently better than the other. They're just different. Further, I also realized that the developers who came before me often had compelling reasons for designing and writing things the way they did. Just because I wasn't privy to it didn't make it untrue. Sure, the documentation could have been better, but still.

So here's where all this leads me:

  1. We have a few tables in the database that have two separate owners. Both owners define identical primary key constraints on the table. This has me perplexed. Why would a table have multiple owners? And why would each owner define separate yet identical primary keys?

  2. These guys designed a pretty well-layed out database with lots of primary keys. But they didn't make a lot of use of indexes. When they did use indexes, they tended to make one large index instead of many distinct indexes. Is there some compelling performance gain to be had from that?

  3. We also avoided foreign key constraints like the plague. Not sure why we would have done that. Is there a reason to avoid them in Oracle? I can see a lot of reasons to use them to enforce data integrity between tables, and we're just not using them. I'm assuming that there's a compelling reason, and I'm just not privy to it.

  4. Finally, is there a compelling reason to avoid the use of triggers (aside from the obvious pitfall that lies in performance hits)? We don't seem to be using those much either.

For the record, we're still using Oracle 9i.

Again, thanks for your patience, everyone. I'm an old Microsoft hand, so bending my brain around the Oracle Way is challenging at times. It's a big beast, with tons to learn, and sometimes, finding that information on the Web is a chore.

Thank His Noodliness for StackOverflow.

Salient Post-Post Points

  • Historically, we haven't used sequences, except in very rare cases.
  • Historically, we haven't used stored procedures or functions, except in very rare cases.
  • There are some references in very old documents to ERWIN. (Thanks to the poster below for bringing it to my memory.) Chances are, the bulk of the design was the product of an ORM, and the natural design flowed from that.
  • The vast majority of the SQL appears hard-coded in the application, and there's a lot of it.
  • I'm doing everything in my power to move us away from hard-coded SQL, and to get the SQL into the database where it belongs. But I'm trying to do that in a way that makes sense, is practical, and doesn't break the business in the process. (Read: On new software only.)
A: 

A lot of people, including me, don't like triggers because it makes it a lot harder to troubleshoot.

This pretty much sums up my opinion

salietata
My considered opinion regarding triggers - either use a lot of them or none. When you have only one or two, they can get forgotten really easily.I have been places that worked both ways and don't see any inherent problems with triggers - as long as everyone remembers that they are there.
Bill
+2  A: 

We have a few tables in the database that have two separate owners. Both owners define identical primary key constraints on the table. This has me perplexed. Why would a table have multiple owners? And why would each owner define separate yet identical primary keys?

You cannot define two PRIMARY KEY's on one table in Oracle. You can define one PRIMARY KEY and one UNIQUE key on the same column set. I can see no point in such a design.

These guys designed a pretty well-layed out database with lots of primary keys. But they didn't make a lot of use of indexes. When they did use indexes, they tended to make one large index instead of many distinct indexes. Is there some compelling performance gain to be had from that?

In Oracle, an index cannot be used for RANGE SCANS on something that doesn't constitute a leftmost prefix of this index.

A composite index on (col1, col2, col3) cannot be used to do a plain RANGE SCAN on col2 alone or col3 alone.

We also avoided foreign key constraints like the plague. Not sure why we would have done that. Is there a reason to avoid them in Oracle? I can see a lot of reasons to use them to enforce data integrity between tables, and we're just not using them. I'm assuming that there's a compelling reason, and I'm just not privy to it.

If you make all interaction with the database through a set of well-defined procedures, a MERGE statement can yield far better performance than a FOREIGN KEY with ON DELETE CASCADE. You, though, should be very very careful and get used to this programming paradigma.

Finally, is there a compelling reason to avoid the use of triggers (aside from the obvious pitfall that lies in performance hits)? We don't seem to be using those much either.

I personally don't use triggers at all. Not every business rule can be expressed in terms of cascading inserts or updates, and any two-pass DML operation will lead to mutating tables. If all interaction with the database is done via stored procedures (or packages), triggers become useless.

Using triggers means in fact using SQL statements inside CURSOR loops, which every SQL cheechako knows to be a bad thing.

You don't want to be seen using cursors instead of set-based operations, do you?

FOREIGN KEY's are not as bad as triggers (as long as you don't define CASCADE operations on them), since they just don't let you do wrong things at the expense of some performance loss.

But when your database grows large, you will notice that the rules for integrity checking are far more complex than just verifying that the values being inserted into one table exist in another one.

You will have to check newly inserted values against aggregates, complex joins, etc., and all will checks will imply having a corresponding value in other table, and failing these checks compromises your database integrity just as good as violating the FOREIGN KEY's

So it will turn out that these FOREIGN KEY's are double and triple checked anyway, and there is no point to keep data integrity rules scattered all around the database rather than having them in one place (a stored procedure that is always used for updating the data).

Quassnoi
+1: No triggers.
S.Lott
Out of curiosity, how do you handle columns like created_date and updated_date? In your opinion, should those be handled at the application level?
Alex Beardsley
@Nalandial: no, they're filled inside the stored procedure which is used to insert the values into the table. It's way faster.
Quassnoi
"there is no point to keep data integrity rules scattered all around the database". Actually the optimizer can make use of constraints in determining optimal execution paths, so there can be benefits in constraints even on pre-validated, read-only data.
Gary
@Gary: could you please give an example? An SQL statement that yields different execution plans depending on whether a FOREIGN KEY is defined or not on one of the tables, all other conditions beign equal?
Quassnoi
+1  A: 

How can the same table belong to two schemas. It doesn't make any sense. That given there is nothing inherently bad practice in the questions you have asked. I develop a large .net application with Oracle database and we have an excellent Oracle DBA in our team. We have used Foreign key constraints wherever possible for data integrity. Triggers are used only to get a new value from sequence or for auditing purpose and not for any business logic. We have used multicolumn unique indexes for data integrity and single column non-unique indexes.

"In Oracle, an index cannot be used for RANGE SCANS on something that doesn't constitute a leftmost prefix."

I believe this is not true anymore since Oracle 10g.

kanad
Sounds to me like it's actually two different tables; potentially holding the same data.
Chris Lively
@kanad: this is true even for 11g. Since 9i, Oracle can do a SKIP SCAN to search for non-leftmost combinations, it's totally different access method which is less efficient than a RANGE SCAN, especially if the leftmost column cardinality is high.
Quassnoi
A: 
  • Lots of primary keys.

  • We also avoided foreign key constraints.

  • Avoid the use of triggers.

Sounds like they used an ORM to fetch objects out of the database. That means fewer ultra-complex joins and SELECT statements and more simple SELECTS. It means constraints in the code, not the database. Similarly, "trigger"-like behavior is in the code.

Doesn't sound Oracle-specific. Sounds like the application has an ORM.

S.Lott
Actually, that rings a bell. There are references in the few (paltry) bits of documentation to ERWIN. Further, there are FEW, if any stored procedures in the database. We use a *lot* of SQL in the code. I'm trying to move us away from that. And no, we don't use sequences, either.
Mike Hofer
A: 

I did Oracle database design for a large organization, and we used triggers as much as we could due to the fact that we had business rules that had to be enforced when data was coming from several directions (the application's GUI, and SQL scripts used for data migration). The business rules we enforced were pretty simple (date checking, checking for existence of rows in another table, etc...). If we tried to make them to complex, we got the dreaded "mutating table" error, which basically means you're trying to inspect the table that is currently changing. So triggers can be useful in some situations, but can cause headaches.

As far as indexes go, in my opinion it is -very- important to have indexes on the columns that are used for joining tables together. That's an easy way to increase performance.

About the foreign keys: since the database changed hands so much, I wonder if the foreign keys could have been dropped accidentally, somewhere along the line. I used PL-SQL developer and some seemingly-innocent operations (like adding/removing a column I think, but I'm not sure) caused the foreign keys to all be deleted.

Jon
A side note: since Oracle has been around for such a long time, it does have some interesting quirks. One difference between Oracle and SQL Server is how they handle nulls; Oracle thinks '' (and empty string) is null.
Jon
A: 

They may have avoided using foreign constraints for performance. I'm told it can be very slow. They also make it difficult to bulk load data which may be inaccurate when loaded but will be corrected programatically.

Jay
A: 

"We have a few tables in the database that have two separate owners. Both owners define identical primary key constraints on the table. This has me perplexed. Why would a table have multiple owners? And why would each owner define separate yet identical primary keys?"

A SQL Server database corresponds more to an Oracle user/schema. So you can have multiple tables in the same Oracle database belonging to different schemas/users. These are DIFFERENT tables (ie with different data inside, and potentially different columns/indexes...).

Sometimes bits of a business want a snaphot of the data (eg at month or year end). Sometimes, before a datafix, a DBA will create a copy of a table (possibly with a different name or in a different schema) just in case the datafix goes horribly wrong. Either way, where you have copies of a table, one is probably out of date (intentionally).

Gary
+1  A: 

"When they did use indexes, they tended to make one large index instead of many distinct indexes. Is there some compelling performance gain to be had from that?"

You create indexes to speed up queries. If you query on "surname = 'Smith' and given_name = 'john'", then it is better to have a single index on (surname, given_name) than two separate indexes.

If no-one is complaining about performance, you probably don't need to worry about indexes.

Gary
A: 

Assuming that you are not in a data warehousing situation here -

  • Foreign keys ensure referential integrity and are absolutely vital. I can't think of a situation when you would not want them.
  • Indexes again are very important tools to ensure query performance.
  • Not sure why they would define PKs without Indexes - PKs are usually implemented via a unique index.
  • Using large indexes, I assume you mean indexes that compound multiple columns

Using ERWIN-engineered Oracle database need not result in such a design - so what you have is not an ERWIN artifact.

If I had to hazard a guess - I am thinking the designer was overly, un-necessarily trying to design for performance - he avoided indexes for update performance, he also avoided FK constraints for a similar 'imagined' performance.

Unless the database is being used for a unique kind of application in a very special way, there really is no grounds for omitting FKs, and Indices.

Regarding triggers, other posters have already weighed in - triggers will be useful for capturing business rules in one central-place (same for Stored Procedures - good for encapsulating Business Logic).

blispr