Permalink
Browse files

Generate MySQL DELETE queries more amenable to optimizations

This MySQL-specific form seems to be subject to more optimizations
than the standard SQL one.
  • Loading branch information...
igstan committed Jul 26, 2016
1 parent 981b1e9 commit 707795f43e24af5a17640a7922cf78de9f436c49
@@ -464,6 +464,10 @@ trait JdbcStatementBuilderComponent { self: JdbcProfile =>
b.build
}
protected def buildDeleteFrom(tableName: String): Unit = {
b"delete from $tableName"
}
def buildDelete: SQLBuilder.Result = {
def fail(msg: String) =
throw new SlickException("Invalid query for DELETE statement: " + msg)
@@ -479,7 +483,7 @@ trait JdbcStatementBuilderComponent { self: JdbcProfile =>
}
val qtn = quoteTableName(from)
symbolName(gen) = qtn // Alias table to itself because DELETE does not support aliases
b"delete from $qtn"
buildDeleteFrom(qtn)
if(!where.isEmpty) {
b" where "
expr(where.reduceLeft((a, b) => Library.And.typed[Boolean](a, b)), true)
@@ -18,6 +18,7 @@ import slick.sql.SqlCapabilities
import slick.util.{SlickLogger, GlobalConfig, ConstArray}
import slick.util.MacroSupport.macroSupportInterpolation
import slick.util.ConfigExtensionMethods.configExtensionMethods
import slick.util.SQLBuilder.Result
/** Slick profile for MySQL.
*
@@ -182,6 +183,24 @@ trait MySQLProfile extends JdbcProfile { profile =>
expr(n)
if(o.direction.desc) b" desc"
}
// Override default DELETE FROM syntax in order to produce a more efficient
// DELETE query for MySQL.
//
// Slick cannot directly handle multi-table DELETEs, i.e., using JOIN or
// USING, but it can handle subqueries in the WHERE clause of a DELETE.
// This is good except for the fact that MySQL doesn't know how to
// optimize such semi-join subqueries to joins in single-table DELETE
// queries. However, if the DELETE query is a multi-table DELETE, even if
// on a single table, then something in MySQL kicks in and optimizes the
// subquery to a more efficient JOIN. Further reading:
//
// - http://mysqlserverteam.com/multi-table-trick
// - https://mariadb.com/kb/en/mariadb/semi-join-subquery-optimizations
//
override protected def buildDeleteFrom(tableName: String): Unit = {
b"delete $tableName from $tableName"
}
}
class UpsertBuilder(ins: Insert) extends super.UpsertBuilder(ins) {

0 comments on commit 707795f

Please sign in to comment.