![]() | ![]() Products ![]() ![]() ![]() ![]() |
Home » Technical Support » ElevateDB Technical Support » Support Forums » ElevateDB SQL » View Thread |
Messages 1 to 10 of 11 total |
![]() |
Mon, Jul 9 2018 7:05 AM | Permanent Link |
Adam Brett Orixa Systems | I have a fairly simple statement:
ALTER TABLE StockPurchaseItems ADD COLUMN UnitWeight FLOAT GENERATED ALWAYS AS ProductWeight(ProductsID) AT 5! The StockPurchaseItems table has about 100,000 rows. The "ProductWeight" function is really fast, it runs in about 0.01 seconds within EDB Manager. However when I run this update script it takes 2 or 3 hours ... My assumption is that EDB is having to do something like re-create an index or something after every row alteration, and this is hugely boosting the time the update takes. Can anyone give me advice on how I might make the ALTER statement run faster? |
Mon, Jul 9 2018 7:30 AM | Permanent Link |
Roy Lambert NLH Associates ![]() | Adam
Unless you need the data to be physically stored would a computed column be faster - it would be slower in use since its much the same as a oncalcfields expression Can you share the code for the function. I do have an idea at the back of my mind but I'd like to check something out when I see what you're doing. Roy Lambert |
Mon, Jul 9 2018 8:59 AM | Permanent Link |
Adam Brett Orixa Systems | Roy
>>Unless you need the data to be physically stored >>would a computed column be faster Can't used "COMPUTED" with a function, you have to use GENERATED When a ROW update happens it is really fast. What is hammering me is the fact that ALTERing the table is taking hours. The ALTER statement MUST be triggering a bunch of other stuff. I am hoping I can avoid or switch this off somehow ... -- >>Can you share the code for the function. It is very simple: CREATE FUNCTION "ProductWeight" (IN "aProductsID" INTEGER) RETURNS FLOAT BEGIN DECLARE Crsr CURSOR FOR Stmt; DECLARE Result FLOAT; PREPARE Stmt FROM ' SELECT UnitWeight FROM Products WHERE ID = ? '; OPEN Crsr USING aProductsID; FETCH FIRST FROM Crsr('UnitWeight') INTO RESULT; RETURN Result; END >>I do have an idea at the back of my mind but I'd >>like to check something out when I see what you're doing. |
Mon, Jul 9 2018 9:00 AM | Permanent Link |
Adam Brett Orixa Systems | OH: And thanks for the feedback Roy! Great to know someone is listening.
|
Mon, Jul 9 2018 9:19 AM | Permanent Link |
Adam Brett Orixa Systems | I have realized that the table is PUBLISHED. It also has links to other tables, and triggers ... so I am guessing that I ought to probably switch off the triggers and publishing during the ALTER, then refresh triggered values afterwards with a single statement.
If I find that this helps I might write it up so it helps someone else not waste a week in the future! |
Mon, Jul 9 2018 9:24 AM | Permanent Link |
Roy Lambert NLH Associates ![]() | Adam
>Can't used "COMPUTED" with a function, you have to use GENERATED Rats, I'd forgotten that ![]() >When a ROW update happens it is really fast. What is hammering me is the fact that ALTERing the table is taking hours. Just taking your 0.01 and 100k rows that would work out to 16 minutes so we're talking 8 - 12 times as long >The ALTER statement MUST be triggering a bunch of other stuff. Do you have any triggers on the table? If so disable them for the table update. Code I use is below my sig. Is the column used in any indices (if so you're mad for putting a FLOAT into an index and deserve anything that happens to you <vbg>). Are other columns computed/generated using UnitWeight? If so that could well be the problem. If the function had been in an external module it could have been linked to CacheModules. I thought DECLARE Crsr CURSOR FOR Stmt; might produce am insensitive result set and it could be a load of disk writes but according to the manual the default is ASENSITIVE which means it should produce a sensitive result set. It might be worth explicitly telling it DECLARE Crsr SENSITIVE CURSOR FOR Stmt; and see if that makes a difference The only thing I have left in my mind is that the statement is being prepared each time. As a test could you replace it with CREATE FUNCTION "ProductWeight" (IN "aProductsID" INTEGER) RETURNS FLOAT DECLARE Result FLOAT; SET Result = 1.2; RETURN Result; END and just see what happens. Sorry I can't give anything definitive Roy procedure UnsetTriggers(const DBase: TEDBDatabase; const TableName: string; Selector: string = ''); var TriggerList: TEDBQuery; begin TriggerList := MakeEDBQuery(DBase); TriggerList.SQL.Text := 'SELECT Name FROM Information.Triggers WHERE TableName = ' + QuotedStr(TableName); if Selector <> '' then TriggerList.SQL.Add(' AND ' + Selector); TriggerList.ExecSQL; while not TriggerList.Eof do begin DBase.Execute('DISABLE TRIGGER "' + TriggerList.FieldByName(F_Name).AsString + '" ON "' + TableName + '"'); TriggerList.Next; end; TriggerList.Free; end; procedure ResetTriggers(const DBase: TEDBDatabase; const TableName: string); var TriggerList: TEDBQuery; begin TriggerList := MakeEDBQuery(DBase); TriggerList.SQL.Text := 'SELECT Name FROM Information.Triggers WHERE TableName = ' + QuotedStr(TableName); TriggerList.ExecSQL; while not TriggerList.Eof do begin DBase.Execute('ENABLE TRIGGER "' + TriggerList.FieldByName(F_Name).AsString + '" ON "' + TableName + '"'); TriggerList.Next; end; TriggerList.Free; end; |
Mon, Jul 9 2018 10:19 AM | Permanent Link |
Adam Brett Orixa Systems | Roy
Thanks! >Can't used "COMPUTED" with a function, you have to use GENERATED >>Rats, I'd forgotten that ![]() ![]() >>Do you have any triggers on the table? If so disable them for >>the table update. Code I use is below my sig. Thanks for this too, I will try it. >>Is the column used in any indices (if so you're mad >>for putting a FLOAT into an index and deserve anything >>that happens to you <vbg>). No! >>Are other columns computed/generated using UnitWeight? >>If so that could well be the problem. There are other computations .... I'm sure this doesn't help, but I can't see how it has the severe impact I am observing. >>If the function had been in an external module it could have been linked to CacheModules. No, but v. good call. >>The only thing I have left in my mind is that the statement is >>being prepared each time. As a test could you replace it with >>CREATE FUNCTION "ProductWeight" (IN "aProductsID" INTEGER) >>RETURNS FLOAT >>DECLARE Result FLOAT; >>SET Result = 1.2; >>RETURN Result; >>END I will try this and report back ... |
Mon, Jul 9 2018 10:23 AM | Permanent Link |
Adam Brett Orixa Systems | One of the strangest things I am finding is how difficult it is to predict the time an ALTER will take.
Some apparently similar changes take seconds while others take hours. It must relate to consequences, such as the presence of Triggers, Published Updates, Indices, or other computed / generated fields. Horribly difficult to figure out which are the worse offenders. |
Mon, Jul 9 2018 10:29 AM | Permanent Link |
Roy Lambert NLH Associates ![]() | Adam
>One of the strangest things I am finding is how difficult it is to predict the time an ALTER will take. > >Some apparently similar changes take seconds while others take hours. > >It must relate to consequences, such as the presence of Triggers, Published Updates, Indices, or other computed / generated fields. Horribly difficult to figure out which are the worse offenders. and don't forget buffering and caching, both ElevateDB's and Window's (and network's), and any other workload that's going on. Roy |
Mon, Jul 9 2018 10:33 AM | Permanent Link |
Roy Lambert NLH Associates ![]() | Adam
Missed this line - sorry >There are other computations .... I'm sure this doesn't help, but I can't see how it has the severe impact I am observing. This can well have an impact depending on what they are - the ultimate would be if the cnages resulted in 100k recalculations which in turn spawned other calculations..... Roy |
Page 1 of 2 | Next Page » | |
Jump to Page: 1 2 |
This web page was last updated on Wednesday, August 14, 2024 at 03:12 PM | Privacy Policy![]() © 2024 Elevate Software, Inc. All Rights Reserved Questions or comments ? ![]() |