[Dbix-Class] Sybase paging performance regressions
Peter Rabbitson
rabbit+dbic at rabbit.us
Mon Jun 21 10:22:27 GMT 2010
thomas Dauby wrote:
> Hi all,
>
> I recently upgraded to DBIx::Class 0.08123, and paging does not work
> anymore.
>
> I get the following error:
>
> query: Error while executing query:DBIx::Class::ResultSet::next():
> Generic Subquery Limit order criteria column 'me.start_time' must be
> unique (no unique constraint found) at VTOM/Repo2.pm line 322 at
> WEB/Action.pm line 119
>
> I modified to order by clause to use a column with a unique contraint,
> but the generated SQL is painfully slow:
>
> SELECT environment_name, start_time, end_time, id, return_status,
> application_name, job_name, duration FROM ( SELECT environment.name
> <http://environment.name> AS environment_name, me.start_time,
> me.end_time, me.id <http://me.id>, me.return_status, application.name
> <http://application.name> AS application_name, job.name
> <http://job.name> AS job_name, me.duration FROM job_exec me JOIN host
> host ON host.id <http://host.id> = me.host_id JOIN users users ON
> users.id <http://users.id> = me.users_id JOIN job job ON job.id
> <http://job.id> = me.job_id JOIN application application ON
> application.id <http://application.id> = job.application_id JOIN
> environment environment ON environment.id <http://environment.id> =
> application.environment_id WHERE ( return_status NOT IN ( ? ) ) ) me
> WHERE ( SELECT COUNT(*) FROM job_exec rownum__emulation WHERE
> rownum__emulation.id <http://rownum__emulation.id> > me.id
> <http://me.id> ) BETWEEN 690 AND 719 ORDER BY me.id <http://me.id> DESC
> : '0'
>
> FYI, here's the generated SQL using the previous version:
>
> SELECT environment.name <http://environment.name>, me.start_time,
> me.end_time, me.id <http://me.id>, me.return_status, application.name
> <http://application.name>, job.name <http://job.name>, me.duration FROM
> job_exec me JOIN host host ON host.id <http://host.id> = me.host_id JOIN
> users users ON users.id <http://users.id> = me.users_id JOIN job job ON
> job.id <http://job.id> = me.job_id JOIN application application ON
> application.id <http://application.id> = job.application_id JOIN
> environment environment ON environment.id <http://environment.id> =
> application.environment_id WHERE ( ( environment.name
> <http://environment.name> = ? AND return_status NOT IN ( ? ) ) ) ORDER
> BY start_time desc: 'paris_divers', '0'
>
> The new SQL comes straight from DBIx::Class::SQLAHacks, but I dont know
> where the old sql comes from...
>
> Is there a way to go back to the old method? I'm not familiar enough
> with the codebase and the code flow to modify it, but I'm using Sybase
> 15, so for this operations, I guess scrollable cursors could be used.
> What shall I modify to do so?
>
Before 08122 DBIx::Class would default to software_limit => 1 when used
with Sybase, because the generic subquery method didn't function at all.
While software_limit is not documented (stupid omission, will be fixed in
the next version) it essentially removes *all* limits from the SQL query
and does the "fast-forwarding" on the client side within DBIC. For a usage
example see [1]. So this is how you can switch between the new and old
method, depending on what will be more beneficial for you.
On your suggestion of "scrollable cursors" - we are very interested into
having this kind of functionality baked into DBIC, could you elaborate more
on how this could work? (best show a pure-DBI example, it will be clearer
for us how to incorporate that into the DBIC machinery)
Cheers!
[1] http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=dbsrgits/DBIx-Class.git;a=blob;f=t/75limit.t;h=686161af223473ebd475d6c563cf71a395dce8ab;hb=refs/heads/master#l29
More information about the DBIx-Class
mailing list