Please start any new threads on our new
site at https://forums.sqlteam.com. We've got lots of great SQL Server
experts to answer whatever question you can come up with.
| Author |
Topic |
|
ThreePea
Yak Posting Veteran
83 Posts |
Posted - 2005-09-13 : 10:27:09
|
Hello. We are trying to increase performance on a few large tables that are heavily accessed real-time in our OLTP system. I am investigating partitioned views. I attended a couple SQL Seminars a while back and pv's were touted as an excellent method of doing some poor man's scaling. I have read BOL and posts here extensively on the subject. I set up a very small and crude system to test (yes, I know the tables don't make sense, it's for example purposes only).SET ANSI_PADDING ONGOCREATE TABLE Test1(Age INT CONSTRAINT CK_Age1 CHECK(Age BETWEEN 1 AND 50),Name VARCHAR(50),CONSTRAINT PK_Test1 PRIMARY KEY CLUSTERED (Age))GOCREATE TABLE Test2(Age INT CONSTRAINT CK_Age2 CHECK(Age BETWEEN 51 AND 100),Name VARCHAR(50),CONSTRAINT PK_Test2 PRIMARY KEY CLUSTERED (Age))GOCREATE VIEW TestASSELECT * FROM Test1UNION ALLSELECT * FROM Test2GOINSERT Test1 VALUES(37,'Jerry')INSERT Test1 VALUES(48,'Bill')INSERT Test1 VALUES(22,'Sue')INSERT Test1 VALUES(11,'Angie')INSERT Test1 VALUES(15,'Kim')INSERT Test1 VALUES(32,'Steve')INSERT Test2 VALUES(82,'Bertha')INSERT Test2 VALUES(59,'Ethel')INSERT Test2 VALUES(99,'Rudolph')INSERT Test2 VALUES(73,'Zelda')INSERT Test2 VALUES(68,'Britney')INSERT Test2 VALUES(51,'Rob')INSERT Test2 VALUES(88,'Jane')GO ------------------------------Now when I run the following query:SELECT *FROM TestWHERE Age = 32 It only hits Test1, which is what I expected. But when I run the following query:SELECT *FROM TestWHERE Age > 60 QA shows it hitting both Test1 and Test2, not just Test1 as I would expect. The strange thing is, when I use the following slightly different syntax, it works as hoped:SELECT *FROM TestWHERE Age > CAST(60 AS INT) Why would CASTing as int make it work? Finally, when using a variable like so:DECLARE @Age INTSET @Age = 88SELECT *FROM TestWHERE Age = @Age The plan shows it hitting both Test1 and Test2. A previous thread on this subject states the reason being the compiler knows the value of @Age could change and therefore the plan has to cover the whole possible range. Ok, I understand. But my question then is, what the heck is the use of partitioned views? How many people run their queries with literal constants instead of parameters/variables on the partitioned column? Unless you set it up as dynamic SQL, I guess. But that's a royal pain in the butt, considering the hundreds of sprocs we already have built hitting these tables.But the classes I went to specifically claimed the main benefit to be not hitting the tables that you don't need. If we throw that out the window then the only advantages left I can see are ease of index maintenance and an escalated table lock only affecting a small subset of the total rows (no small benefit, to be sure, but I wanted more). Am I looking at this correctly? Thanks for your comments.=============================================3P |
|
|
mr_mist
Grunnio
1870 Posts |
Posted - 2005-09-13 : 11:13:23
|
| I found that the constraints had to be re-run after data loads for them to be effective, and you'd need to use the WITH CHECK option. Generally my experience with the performance of partitioned views was that it was not great, especially for GROUP BYs with operators that spanned the various tables.-------Moo. :) |
 |
|
|
mmarovic
Aged Yak Warrior
518 Posts |
Posted - 2005-09-13 : 12:13:15
|
quote:
DECLARE @Age INTSET @Age = 88SELECT *FROM TestWHERE Age = @Age The plan shows it hitting both Test1 and Test2. A previous thread on this subject states the reason being the compiler knows the value of @Age could change and therefore the plan has to cover the whole possible range. Ok, I understand. But my question then is, what the heck is the use of partitioned views? How many people run their queries with literal constants instead of parameters/variables on the partitioned column? Unless you set it up as dynamic SQL, I guess. But that's a royal pain in the butt, considering the hundreds of sprocs we already have built hitting these tables.
It works like that if you have batch outside sp. However, if @Age is sp input parameter, optimal execution plan may be constructed. However, you may expect frequent sp recompilations. I don't know if it actually works like that, I haven't used partitioned views for years. I remember we used mixture of procs accessing directly specific tables and queries actually used partitioned view, but I an not sure about details anymore. |
 |
|
|
ThreePea
Yak Posting Veteran
83 Posts |
Posted - 2005-09-13 : 16:44:51
|
quote: Originally posted by mr_mist I found that the constraints had to be re-run after data loads for them to be effective, and you'd need to use the WITH CHECK option.
Yeah, tried this, it didn't work.And mmarovic, I did construct a sp with @Age as a parameter, but it still referenced both tables. Maybe I'll try it with one of our big tables and see if I get an positive results.Man, I love SQL Server, but I'm frustrated to no end trying to do any type of scaling-out methodology that involves near real-time data. Every promising piece of technology or method falters at the end with some unforseen "gotcha." Thanks.==================================================Tolerance is the last virtue of an immoral society. -- G.K. Chesterton |
 |
|
|
MichaelP
Jedi Yak
2489 Posts |
Posted - 2005-09-13 : 17:59:54
|
| Maybe this is a case where scanning both tables is more effecient than hitting the "proper" indexes? I seem to recall running into that sort of thing when I was builing my DPV. Maybe put a few million rows into those tables, update the statistics, and then run your stored procs.Michael<Yoda>Use the Search page you must. Find the answer you will. Cursors, path to the Dark Side they are. Avoid them, you must. Use Order By NewID() to get a random record you will.</Yoda> |
 |
|
|
mmarovic
Aged Yak Warrior
518 Posts |
Posted - 2005-09-14 : 03:07:38
|
| I also remember that we had strange problem. When we had select * or select <all columns> queries we had execution plan that accessed all tables but when we removed at least one column from column list, a "good" plan was executed all of sudden. |
 |
|
|
Kristen
Test
22859 Posts |
Posted - 2005-09-14 : 06:40:13
|
| My $0.02 is that this approach is kinda out-of-sight out-of-mind - niffty work around by the query plan stuff, which is very dependant on following the rules to the letter.There was a post recently about someone who had changed an int to a decimal() or somesuch and it broke the partition because not all the tables had the exact datatype of that column. Result? Slow running - not error :-(The deal with SP4 on queries where the datatype on both sides of the JOIN is different which causes slow running is painful too.I wouldn't mind some "debug mode" that moaned about all these - like the Level 4 Warnings in compilers. It could tell me which column or which row, and its value, in an import was breaking an FK too.I expect SQL2005 does all this and more?I'm sure you've checked that you adhere to the "rules" for Horizontal Partition, but in case of interest there is a synopsis posted here:http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=54747Kristen |
 |
|
|
|
|
|
|
|