Subject | Re: Why is Interbase so slow? |
---|---|
Author | john@equatorIT.com |
Post date | 2001-09-30T15:07:05Z |
Carl,
Thanks for your rigourous work.
This at least shows me clearly where I have to go, without spending a
lot of time fiddling at the edges.
I used SQL_SERVER 2000, but also loaded the data into MSDE - it took
2 secs (or less) too.
I guess the optimiser in MS databases is fairly good, and using
procedures with MS would give even better results.
Thanks again Carl for investigating this ...
John
Thanks for your rigourous work.
This at least shows me clearly where I have to go, without spending a
lot of time fiddling at the edges.
I used SQL_SERVER 2000, but also loaded the data into MSDE - it took
2 secs (or less) too.
I guess the optimiser in MS databases is fairly good, and using
procedures with MS would give even better results.
Thanks again Carl for investigating this ...
John
--- In ib-support@y..., Carl van Tast <vanTast@a...> wrote:
> Hi John, Helen, Ann et al.
>
> Sorry for the long message.
>
> On Tue, 25 Sep 2001 18:36:01 +0000 (UTC), john@e... wrote:
> >[...]
> >
> >UPDATE ENROL E
> >SET REVENUE_NO = (
> > SELECT REVENUE_NO
> > FROM REVENUE_FACULTY RF, STUDENT S
> > WHERE S.STUD_NO = E.stud_no
> > AND RF.CRT_NO = E.crt_no
> > AND RF.OS = S.OS)
> >[...]
> >This took about 2 hours to run...
> >
> >What am I doing wrong?
>
> I don't know, but out of curiosity I made a few tests. For those
> interested I post my results here. The tests were run with
Interbase
> 6.0 (referred to as IB in this post), PostgreSQL 7.1.3 (PG) and two
> prot^Hper^H^Hrilit^H^H... , well, commercial database servers (M7
and
> O7).
> Hardware and OS:
> P II 300MHz, 128MB, W2K Pro for IB, PG, M7
> AMB K6 180MHZ, 256MB, NT Server for O7
> All database servers installed out of the box, no special tuning
(see
> note at end).
>
> All times are in minutes and seconds, first value without indices,
> second value with indices.
>
> John did not tell us his metadata, so I had to guess:
>
> CREATE TABLE enrol (
> stud_no INTEGER NOT NULL,
> crt_no INTEGER NOT NULL,
> revenue_no INTEGER
> /*,
> UNIQUE (stud_no, crt_no)
> */
> );
>
> CREATE TABLE revenue_faculty (
> revenue_no INTEGER NOT NULL,
> crt_no INTEGER NOT NULL,
> os INTEGER NOT NULL
> /*,
> PRIMARY KEY (revenue_no),
> UNIQUE (crt_no, os)
> */
> );
>
> CREATE TABLE student (
> stud_no INTEGER NOT NULL,
> os INTEGER NOT NULL
> /*,
> PRIMARY KEY (stud_no)
> */
> );
>
> The tables were populated with following stored procedures:
>
> SET TERM | ;
> CREATE PROCEDURE enrol_fill
> AS
> DECLARE VARIABLE stud INTEGER;
> DECLARE VARIABLE crt INTEGER;
> DECLARE VARIABLE cnt INTEGER;
> BEGIN
> stud = 0;
> crt = 0;
> cnt = 0;
> WHILE (cnt < 10000) DO BEGIN
> cnt = cnt + 1;
> stud = stud + 1;
> IF (stud > 7001) THEN BEGIN
> stud = 1;
> END
> crt = crt + 1;
> IF (crt > 10) THEN BEGIN
> crt = 1;
> END
> INSERT INTO enrol (stud_no, crt_no) VALUES (:stud, :crt);
> END
> END|
>
> CREATE PROCEDURE student_fill
> AS
> DECLARE VARIABLE stud INTEGER;
> DECLARE VARIABLE os INTEGER;
> DECLARE VARIABLE cnt INTEGER;
> BEGIN
> stud = 0;
> os = 0;
> cnt = 0;
> WHILE (cnt < 7000) DO BEGIN
> cnt = cnt + 1;
> stud = stud + 1;
> os = os + 1;
> IF (os > 3) THEN BEGIN
> os = 1;
> END
> INSERT INTO student (stud_no, os) VALUES (:stud, :os);
> END
> END|
>
> CREATE PROCEDURE revenue_faculty_fill
> AS
> BEGIN
> INSERT INTO revenue_faculty VALUES (123456, 1, 1);
> INSERT INTO revenue_faculty VALUES (123457, 2, 2);
> INSERT INTO revenue_faculty VALUES (123458, 3, 1);
> INSERT INTO revenue_faculty VALUES (123459, 4, 2);
> INSERT INTO revenue_faculty VALUES (123460, 5, 3);
> INSERT INTO revenue_faculty VALUES (123461, 6, 1);
> INSERT INTO revenue_faculty VALUES (123462, 7, 2);
> INSERT INTO revenue_faculty VALUES (123463, 8, 1);
> INSERT INTO revenue_faculty VALUES (123464, 9, 3);
> INSERT INTO revenue_faculty VALUES (123465, 10, 2);
> END|
> SET TERM ; |
>
> EXECUTE PROCEDURE enrol_fill;
> -- IB: 0:01.0 / 0:02
> -- PG: 0:03.5 / 0:04.7
> -- M7: 0:06 / 0:06
> -- O7: 0:41 / 1:41
>
> EXECUTE PROCEDURE student_fill;
> -- IB: 0:00.9 / 0:01.4
> -- PG: 0:02.5 / 0:03.3
> -- M7: 0:04 / 0:04
> -- O7: 0:36 / 0:57
>
> EXECUTE PROCEDURE revenue_faculty_fill;
> -- IB, PG, M7: instantly
>
> Note: Without explicit BEGIN/COMMIT TRANSACTION times jump up to
1:55
> for enrol_fill resp. 1:20 for student_fill in M7, +/- a few seconds
> for with/without index.
>
> -- test:
> SELECT count(*)
> FROM enrol e, revenue_faculty rf, student s
> WHERE s.stud_no = e.stud_no
> AND rf.crt_no = e.crt_no
> AND rf.os = s.os;
> -- correct answer is 3333
> -- IB: 0:01.6 / 0:01.6
> -- PG: 0:03.1 / 0:01.7
> -- M7: 0:00.9 / 0:01
> -- O7: 0:03.4 / 0:01.8
>
> -- John's update:
> UPDATE enrol e
> SET revenue_no = (
> SELECT revenue_no
> FROM revenue_faculty rf, student s
> WHERE s.stud_no = e.stud_no
> AND rf.crt_no = e.crt_no
> AND rf.os = s.os);
> -- IB: 66:00 / 66:00
> -- PG: 4:40 / 0:05.4
> -- M7: 2:16 / 0:02
> -- O7: >>180 / 0:35
>
> UPDATE enrol
> SET revenue_no = rf.revenue_no
> FROM revenue_faculty rf, student s
> WHERE s.stud_no = enrol.stud_no
> AND rf.crt_no = enrol.crt_no
> AND rf.os = s.os;
> -- IB: doesn't work
> -- PG: 0:03.4 / 0:02.5
> -- M7: 0:01 / 0:01
> -- O7: doesn't work
>
> -- Helen's procedure
> SET TERM | ;
> CREATE PROCEDURE update_enrol
> AS
> DECLARE VARIABLE vrevenue_no INTEGER;
> DECLARE VARIABLE vcrt_no INTEGER;
> DECLARE VARIABLE vstud_no INTEGER;
> BEGIN
> FOR SELECT rf.revenue_no,
> rf.crt_no,
> s.stud_no
> FROM revenue_faculty rf
> JOIN student s
> ON rf.os = s.os
> INTO :vrevenue_no, :vcrt_no, :vstud_no DO
> BEGIN
> UPDATE enrol
> SET revenue_no = :vrevenue_no
> WHERE stud_no = :vstud_no
> AND crt_no = :vcrt_no;
> END
> END|
> SET TERM ; |
>
> EXECUTE PROCEDURE update_enrol;
> -- IB: 50:00
>
> This procedure has to update 3333 rows, but
> SELECT ... FROM rf JOIN s ...
> selects 23334 rows, so on average each row is updated seven times.
I
> did no more tests with this procedure and used the following
instead:
>
> SET TERM | ;
> CREATE PROCEDURE update_enrol2
> AS
> DECLARE VARIABLE vrevenue_no INTEGER;
> DECLARE VARIABLE vcrt_no INTEGER;
> DECLARE VARIABLE vstud_no INTEGER;
> BEGIN
> FOR SELECT rf.revenue_no,
> rf.crt_no,
> s.stud_no
> FROM revenue_faculty rf
> JOIN student s
> ON rf.os = s.os
> JOIN enrol e
> ON e.stud_no=s.stud_no AND e.crt_no=rf.crt_no
> INTO :vrevenue_no, :vcrt_no, :vstud_no DO
> BEGIN
> UPDATE enrol
> SET revenue_no = :vrevenue_no
> WHERE stud_no = :vstud_no
> AND crt_no = :vcrt_no;
> END
> END|
> SET TERM ; |
>
> EXECUTE PROCEDURE update_enrol2;
> -- IB: 7:30 / 0:02.6
> -- PG: 6:25 / 0:07
> -- M7: 8:41 / 0:04
> -- O7: 5:29 / 0:11
>
> Again you have to include BEGIN/COMMIT TRANSACTION for M7.
Execution
> time would be 9:33 / 0:41 without.
>
> Re tuning:
> On Thu, 27 Sep 2001 17:34:41 +0000 (UTC), aharrison@i...
> ("Ann W. Harrison") wrote:
> >> > >DATABASE_CACHE_PAGES 75
> >
> >I'd strongly suggest increasing this to at least 2500 if you're
> >running SS. You may see better performance at 5000.
>
> Well, after setting this parameter to 2500 and restarting IB I
> repeated my tests and I got *exactly* the same times. This can be
> explained by the fact that the machine is almost 100% CPU bound
during
> these tests. Disk IO is not an issue here. Or did I do something
> wrong?
>
> Conclusions:
>
> . Both open source databases offer good performance when used
> properly.
>
> . The more modern commercial product seems to be faster with
> complex SQL statements. (The other one is almost ten years
old.)
>
> . IB and PG have really fast stored procedure execution engines.
>
> . Data design and choice of algorithm have great influence on
> performance. Using the same hardware and software, you can do
the
> same job in 3 seconds or in more than 1 hour.
>
> . UPDATE ... FROM would help a lot.
>
> Please don't flame me for doing my tests on different hardware.
> Correct the results by a factor 2 or 3, if you want. IMHO
conclusions
> are still valid.
>
> If I made a mistake or you think the times measured should be
> interpreted differently, let me know. I'll happily correct this
> document and make it available again, though not necessarily on this
> mailing list; it's really too long for sending it more than once.
>
> >
> >Thanks in advance for any clues.
> >
> >John Newcombe
>
> .02 by
> Carl van Tast
> >
> >
> >PS Sacrilege - I datapumped the entire database into a sql_server
db -
> >and ran the exact same query with no indexes and it took 2 secs!!
>
> Not a sacrileg, just valuable information. But what kind of
> sql_server?