Skip to content

DDC-1602: Executors for Class Table Inheritance (JOINED) are extremely slow on MySQL #2240

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
doctrinebot opened this issue Jan 15, 2012 · 4 comments
Assignees

Comments

@doctrinebot
Copy link

Jira issue originally created by user majkl578:

Update and delete executors for Class Table Inheritance (JOINED) are extremely slow on MySQL platform. It is most probably due to use of subselect on the temporary table.
The slowdown is really significant as the table size increases. As an example, lets have a root entity with one subclass:

/****
 * @Entity
 * @InheritanceType("JOINED")
 * @DiscriminatorColumn(name="discr", type="string")
 * @DiscriminatorMap({"root" = "Root", "a" = "SubA"})
 */
class Root
{
    /****
     * @Column(type="integer")
     * @Id
     * @GeneratedValue
     */
    private $id;

    /****
     * @Column(type="integer")
     */
    private $xyz;
}
/****
 * @Entity
 */
class SubA extends Root
{
    /****
     * @Column(type="integer")
     */
    private $foo;
}

Now lets perform a simple DQL UPDATE:

UPDATE Entities\Root r SET r.xyz = 123 WHERE r.id > ?

(note: always the upper half of entries)
Which creates following SQLs:

CREATE TEMPORARY TABLE Root*id*tmp (id INT NOT NULL)
INSERT INTO Root*id_tmp (id) SELECT t0.id FROM Root t0 LEFT JOIN SubA s0_ ON t0.id = s0*.id WHERE t0.id > 25000
UPDATE Root SET xyz = 123 WHERE (id) IN (SELECT id FROM Root*id*tmp)
DROP TEMPORARY TABLE Root*id*tmp

The time spent on this on MySQL 5.5.17 and PostgreSQL 9.1 is:

|| no. of entries || 500 || 1000 || 2500 || 5000 || 10000 || 20000 || 50000 ||
| MySQL | 0.26s | 0.35s | 1.1s | 3.68s | 14.13s | 54.44s | 338s |
| PostgreSQL | 0.10s | 0.10s | 0.13s | 0.15s | 0.22s | 0.35s | 1.01s |

As you can see, MySQL is drastically slower on even relatively small tables. This currently makes Doctrine unusable for this type of inheritance on MySQL. The solution probably would be to avoid subselect in WHERE clause in Doctrine\ORM\Query\Exec\MultiTableUpdateExecutor and Doctrine\ORM\Query\Exec\MultiTableDeleteExecutor.

Feel free to try/modify the test script yourself, it's here.

@doctrinebot
Copy link
Author

Comment created by @beberlei:

Its not a bug as it works. The performance drawback of JTI is discussed in the manual http://www.doctrine-project.org/docs/orm/2.1/en/reference/inheritance-mapping.html.

Changing this would be an improvement where we would hint if databases prefer subselects or joins for different operations. This would increase complexity of the SQL generation since now we are getting along with just one SQL generation strategy.

@doctrinebot
Copy link
Author

Comment created by majkl578:

Any chance to get this implemented before 2.3?

@doctrinebot
Copy link
Author

Comment created by majkl578:

I've made a change in DBAL and ORM code to implement a solution issue. It's currently more likely a proof of concept.

With the change, my results are (approximately):
|| no. of entries || 500 || 1000 || 2500 || 5000 || 10000 || 20000 || 50000 ||
| MySQL | 0.17s | 0.19s | 0.21s | 0.26s | 0.27s | 0.37s | 0.92s |

Currently only update executor was changed.
DBAL branch with changes: https://github.com/Majkl578/doctrine-dbal/tree/[DDC-1602](http://www.doctrine-project.org/jira/browse/DDC-1602)
ORM branch with changes: https://github.com/Majkl578/doctrine2/tree/[DDC-1602](http://www.doctrine-project.org/jira/browse/DDC-1602)

Looking forward for your opinions.

@doctrinebot
Copy link
Author

Comment created by majkl578:

bump

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants