diff --git a/util/sqlgen/benchmark_test.go b/util/sqlgen/benchmark_test.go
index f04428ae3945f06677e044d7934a67d938906b84..3cc2e25f2052bf6705902427aaf5cc419cbd3bf6 100644
--- a/util/sqlgen/benchmark_test.go
+++ b/util/sqlgen/benchmark_test.go
@@ -1,6 +1,8 @@
 package sqlgen
 
 import (
+	"fmt"
+	"math/rand"
 	"testing"
 )
 
@@ -47,8 +49,29 @@ func BenchmarkTable(b *testing.B) {
 }
 
 func BenchmarkCompileTable(b *testing.B) {
+	var t string
 	for i := 0; i < b.N; i++ {
-		_ = Table{"foo"}.Compile(defaultTemplate)
+		t = Table{"foo"}.Compile(defaultTemplate)
+		if t != `"foo"` {
+			b.Fatal("Caching failed.")
+		}
+	}
+}
+
+func BenchmarkCompileRandomTable(b *testing.B) {
+	var t string
+	var m, n int
+	var s, e string
+
+	for i := 0; i < b.N; i++ {
+		m, n = rand.Int(), rand.Int()
+		s = fmt.Sprintf(`%s as %s`, m, n)
+		e = fmt.Sprintf(`"%s" AS "%s"`, m, n)
+
+		t = Table{s}.Compile(defaultTemplate)
+		if t != e {
+			b.Fatal()
+		}
 	}
 }
 
diff --git a/util/sqlgen/default.go b/util/sqlgen/default.go
index 0c855a6acb4ca5e742c1ba11d50f33c7874611dc..9038db0fa9cd0eb9097c815ebc7f26edee4391f8 100644
--- a/util/sqlgen/default.go
+++ b/util/sqlgen/default.go
@@ -142,4 +142,5 @@ var defaultTemplate = &Template{
 	defaultSelectCountLayout,
 	defaultGroupByLayout,
 	nil,
+	nil,
 }
diff --git a/util/sqlgen/table.go b/util/sqlgen/table.go
index 50331770a9b0601e16c489f39fb3463e4a8dcf01..141c4dc2052c2b34d0b369b9077c41f419edba02 100644
--- a/util/sqlgen/table.go
+++ b/util/sqlgen/table.go
@@ -21,12 +21,14 @@ type Table struct {
 }
 
 func quotedTableName(layout *Template, input string) string {
-	input = strings.TrimSpace(input)
+	input = trimString(input)
 
-	chunks := reAliasSeparator.Split(input, 2)
+	// chunks := reAliasSeparator.Split(input, 2)
+	chunks := separateByAS(input)
 
 	if len(chunks) == 1 {
-		chunks = reSpaceSeparator.Split(input, 2)
+		// chunks = reSpaceSeparator.Split(input, 2)
+		chunks = separateBySpace(input)
 	}
 
 	name := chunks[0]
@@ -34,7 +36,8 @@ func quotedTableName(layout *Template, input string) string {
 	nameChunks := strings.SplitN(name, layout.ColumnSeparator, 2)
 
 	for i := range nameChunks {
-		nameChunks[i] = strings.TrimSpace(nameChunks[i])
+		// nameChunks[i] = strings.TrimSpace(nameChunks[i])
+		nameChunks[i] = trimString(nameChunks[i])
 		nameChunks[i] = mustParse(layout.IdentifierQuote, Raw{nameChunks[i]})
 	}
 
@@ -43,7 +46,8 @@ func quotedTableName(layout *Template, input string) string {
 	var alias string
 
 	if len(chunks) > 1 {
-		alias = strings.TrimSpace(chunks[1])
+		// alias = strings.TrimSpace(chunks[1])
+		alias = trimString(chunks[1])
 		alias = mustParse(layout.IdentifierQuote, Raw{alias})
 	}
 
@@ -56,16 +60,29 @@ func (self Table) Hash() string {
 
 func (self Table) Compile(layout *Template) (compiled string) {
 
-	// Splitting tables by a comma
-	parts := reTableSeparator.Split(self.Name, -1)
+	if self.Name == "" {
+		return
+	}
 
-	l := len(parts)
+	if layout.isCached(self) {
 
-	for i := 0; i < l; i++ {
-		parts[i] = quotedTableName(layout, parts[i])
-	}
+		compiled = layout.getCache(self)
+
+	} else {
+
+		// Splitting tables by a comma
+		parts := separateByComma(self.Name)
 
-	compiled = strings.Join(parts, layout.IdentifierSeparator)
+		l := len(parts)
+
+		for i := 0; i < l; i++ {
+			parts[i] = quotedTableName(layout, parts[i])
+		}
+
+		compiled = strings.Join(parts, layout.IdentifierSeparator)
+
+		layout.setCache(self, compiled)
+	}
 
-	return compiled
+	return
 }
diff --git a/util/sqlgen/table_test.go b/util/sqlgen/table_test.go
index d6a88c736d740570ab763702ad8427e43f04d99e..dbae8be34841b8255a383c519fbd32d8b0444f43 100644
--- a/util/sqlgen/table_test.go
+++ b/util/sqlgen/table_test.go
@@ -87,3 +87,31 @@ func TestTableMultipleAlias(t *testing.T) {
 		t.Fatalf("Got: %s, Expecting: %s", s, e)
 	}
 }
+
+func TestTableMinimal(t *testing.T) {
+	var s, e string
+	var table Table
+
+	table = Table{"a"}
+
+	s = trim(table.Compile(defaultTemplate))
+	e = `"a"`
+
+	if s != e {
+		t.Fatalf("Got: %s, Expecting: %s", s, e)
+	}
+}
+
+func TestTableEmpty(t *testing.T) {
+	var s, e string
+	var table Table
+
+	table = Table{""}
+
+	s = trim(table.Compile(defaultTemplate))
+	e = ``
+
+	if s != e {
+		t.Fatalf("Got: %s, Expecting: %s", s, e)
+	}
+}
diff --git a/util/sqlgen/template.go b/util/sqlgen/template.go
index ac399094ff8860fb0562651ea3d7566f3c783c7d..7502e27f73b0b80bf92916d98d4241ceac3d31c4 100644
--- a/util/sqlgen/template.go
+++ b/util/sqlgen/template.go
@@ -30,6 +30,11 @@ type Template struct {
 	SelectCountLayout   string
 	GroupByLayout       string
 	cache               map[interface{}]string
+	cachedTemplates     map[string]string
+}
+
+type cacheable interface {
+	Hash() string
 }
 
 func (self *Template) SetCache(key interface{}, value string) {
@@ -47,3 +52,27 @@ func (self *Template) Cache(key interface{}) (string, bool) {
 	}
 	return "", false
 }
+
+func (self *Template) getCache(i cacheable) string {
+	if self.cachedTemplates == nil {
+		return ""
+	}
+	return self.cachedTemplates[i.Hash()]
+}
+
+func (self *Template) setCache(i cacheable, s string) {
+	if self.cachedTemplates == nil {
+		self.cachedTemplates = map[string]string{}
+	}
+	self.cachedTemplates[i.Hash()] = s
+}
+
+func (self *Template) isCached(i cacheable) bool {
+	if self.cachedTemplates == nil {
+		return false
+	}
+	if _, ok := self.cachedTemplates[i.Hash()]; ok {
+		return true
+	}
+	return false
+}
diff --git a/util/sqlgen/utilities.go b/util/sqlgen/utilities.go
new file mode 100644
index 0000000000000000000000000000000000000000..40bfe1e04ab17d458df54f2b5eac3f68f69e1f29
--- /dev/null
+++ b/util/sqlgen/utilities.go
@@ -0,0 +1,149 @@
+package sqlgen
+
+import (
+	"strings"
+)
+
+const (
+	stageExpect = iota
+	stageCapture
+	stageClose
+)
+
+func isSpace(in byte) bool {
+	return in == ' ' || in == '\t' || in == '\r' || in == '\n'
+}
+
+func trimString(in string) string {
+
+	start, end := 0, len(in)-1
+
+	// Where do we start cutting?
+	for ; start <= end; start++ {
+		if isSpace(in[start]) == false {
+			break
+		}
+	}
+
+	// Where do we end cutting?
+	for ; end >= start; end-- {
+		if isSpace(in[end]) == false {
+			break
+		}
+	}
+
+	return in[start : end+1]
+}
+
+func trimByte(in []byte) []byte {
+
+	start, end := 0, len(in)-1
+
+	// Where do we start cutting?
+	for ; start <= end; start++ {
+		if isSpace(in[start]) == false {
+			break
+		}
+	}
+
+	// Where do we end cutting?
+	for ; end >= start; end-- {
+		if isSpace(in[end]) == false {
+			break
+		}
+	}
+
+	return in[start : end+1]
+}
+
+/*
+// Separates by a comma, ignoring spaces too.
+// This was slower than strings.Split.
+func separateByComma(in string) (out []string) {
+
+	out = []string{}
+
+	start, lim := 0, len(in)-1
+
+	for start < lim {
+		var end int
+
+		for end = start; end <= lim; end++ {
+			// Is a comma?
+			if in[end] == ',' {
+				break
+			}
+		}
+
+		out = append(out, trimString(in[start:end]))
+
+		start = end + 1
+	}
+
+	return
+}
+*/
+
+// Separates by a comma, ignoring spaces too.
+func separateByComma(in string) (out []string) {
+	out = strings.Split(in, ",")
+	for i := range out {
+		out[i] = trimString(out[i])
+	}
+	return
+}
+
+// Separates by spaces, ignoring spaces too.
+func separateBySpace(in string) (out []string) {
+	l := len(in)
+
+	if l == 0 {
+		return []string{""}
+	}
+
+	out = make([]string, 0, l)
+
+	pre := strings.Split(in, " ")
+
+	for i := range pre {
+		pre[i] = trimString(pre[i])
+		if pre[i] != "" {
+			out = append(out, pre[i])
+		}
+	}
+
+	return
+}
+
+func separateByAS(in string) (out []string) {
+	out = []string{}
+
+	if len(in) < 6 {
+		// Min expression: "a AS b"
+		return []string{in}
+	}
+
+	start, lim := 0, len(in)-1
+
+	for start <= lim {
+		var end int
+
+		for end = start; end <= lim; end++ {
+			if end > 3 && isSpace(in[end]) && isSpace(in[end-3]) {
+				if (in[end-1] == 's' || in[end-1] == 'S') && (in[end-2] == 'a' || in[end-2] == 'A') {
+					break
+				}
+			}
+		}
+
+		if end < lim {
+			out = append(out, trimString(in[start:end-3]))
+		} else {
+			out = append(out, trimString(in[start:end]))
+		}
+
+		start = end + 1
+	}
+
+	return
+}
diff --git a/util/sqlgen/utilities_test.go b/util/sqlgen/utilities_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..87cff171c458d7b80a817a5c58d1d9398dfba091
--- /dev/null
+++ b/util/sqlgen/utilities_test.go
@@ -0,0 +1,271 @@
+package sqlgen
+
+import (
+	"bytes"
+	"regexp"
+	"strings"
+	"testing"
+)
+
+func TestUtilIsSpace(t *testing.T) {
+	if isSpace(' ') == false {
+		t.Fail()
+	}
+	if isSpace('\n') == false {
+		t.Fail()
+	}
+	if isSpace('\t') == false {
+		t.Fail()
+	}
+	if isSpace('\r') == false {
+		t.Fail()
+	}
+	if isSpace('x') == true {
+		t.Fail()
+	}
+}
+
+func TestUtilTrimByte(t *testing.T) {
+	var trimmed []byte
+
+	trimmed = trimByte([]byte("  \t\nHello World!     \n"))
+	if string(trimmed) != "Hello World!" {
+		t.Fatalf("Got: %s\n", string(trimmed))
+	}
+
+	trimmed = trimByte([]byte("Nope"))
+	if string(trimmed) != "Nope" {
+		t.Fatalf("Got: %s\n", string(trimmed))
+	}
+
+	trimmed = trimByte([]byte(""))
+	if string(trimmed) != "" {
+		t.Fatalf("Got: %s\n", string(trimmed))
+	}
+
+	trimmed = trimByte(nil)
+	if string(trimmed) != "" {
+		t.Fatalf("Got: %s\n", string(trimmed))
+	}
+}
+
+func TestUtilSeparateByComma(t *testing.T) {
+	chunks := separateByComma("Hello,,World!,Enjoy")
+
+	if len(chunks) != 4 {
+		t.Fatal()
+	}
+
+	if chunks[0] != "Hello" {
+		t.Fatal()
+	}
+	if chunks[1] != "" {
+		t.Fatal()
+	}
+	if chunks[2] != "World!" {
+		t.Fatal()
+	}
+	if chunks[3] != "Enjoy" {
+		t.Fatal()
+	}
+}
+
+func TestUtilSeparateBySpace(t *testing.T) {
+	chunks := separateBySpace("       Hello        World!        Enjoy")
+
+	if len(chunks) != 3 {
+		t.Fatal()
+	}
+
+	if chunks[0] != "Hello" {
+		t.Fatal()
+	}
+	if chunks[1] != "World!" {
+		t.Fatal()
+	}
+	if chunks[2] != "Enjoy" {
+		t.Fatal()
+	}
+}
+
+func TestUtilSeparateByAS(t *testing.T) {
+	var chunks []string
+
+	var tests = []string{
+		`table.Name AS myTableAlias`,
+		`table.Name     AS         myTableAlias`,
+		"table.Name\tAS\r\nmyTableAlias",
+	}
+
+	for _, test := range tests {
+		chunks = separateByAS(test)
+
+		if len(chunks) != 2 {
+			t.Fatalf(`Expecting 2 results.`)
+		}
+
+		if chunks[0] != "table.Name" {
+			t.Fatal(`Expecting first result to be "table.Name".`)
+		}
+		if chunks[1] != "myTableAlias" {
+			t.Fatal(`Expecting second result to be myTableAlias.`)
+		}
+	}
+
+	// Single character.
+	chunks = separateByAS("a")
+
+	if len(chunks) != 1 {
+		t.Fatalf(`Expecting 1 results.`)
+	}
+
+	if chunks[0] != "a" {
+		t.Fatal(`Expecting first result to be "a".`)
+	}
+
+	// Empty name
+	chunks = separateByAS("")
+
+	if len(chunks) != 1 {
+		t.Fatalf(`Expecting 1 results.`)
+	}
+
+	if chunks[0] != "" {
+		t.Fatal(`Expecting first result to be "".`)
+	}
+
+	// Single name
+	chunks = separateByAS("  A Single Table ")
+
+	if len(chunks) != 1 {
+		t.Fatalf(`Expecting 1 results.`)
+	}
+
+	if chunks[0] != "A Single Table" {
+		t.Fatal(`Expecting first result to be "ASingleTable".`)
+	}
+
+	// Minimal expression.
+	chunks = separateByAS("a AS b")
+
+	if len(chunks) != 2 {
+		t.Fatalf(`Expecting 2 results.`)
+	}
+
+	if chunks[0] != "a" {
+		t.Fatal(`Expecting first result to be "a".`)
+	}
+
+	if chunks[1] != "b" {
+		t.Fatal(`Expecting first result to be "b".`)
+	}
+
+	// Minimal expression with spaces.
+	chunks = separateByAS("   a    AS    b ")
+
+	if len(chunks) != 2 {
+		t.Fatalf(`Expecting 2 results.`)
+	}
+
+	if chunks[0] != "a" {
+		t.Fatal(`Expecting first result to be "a".`)
+	}
+
+	if chunks[1] != "b" {
+		t.Fatal(`Expecting first result to be "b".`)
+	}
+
+	// Minimal expression + 1 with spaces.
+	chunks = separateByAS("   a    AS    bb ")
+
+	if len(chunks) != 2 {
+		t.Fatalf(`Expecting 2 results.`)
+	}
+
+	if chunks[0] != "a" {
+		t.Fatal(`Expecting first result to be "a".`)
+	}
+
+	if chunks[1] != "bb" {
+		t.Fatal(`Expecting first result to be "bb".`)
+	}
+}
+
+func BenchmarkUtilIsSpace(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		_ = isSpace(' ')
+	}
+}
+
+func BenchmarkUtilTrimByte(b *testing.B) {
+	s := []byte("               Hello world!             ")
+	for i := 0; i < b.N; i++ {
+		_ = trimByte(s)
+	}
+}
+
+func BenchmarkUtilTrimString(b *testing.B) {
+	s := "               Hello world!             "
+	for i := 0; i < b.N; i++ {
+		_ = trimString(s)
+	}
+}
+
+func BenchmarkUtilStdBytesTrimSpace(b *testing.B) {
+	s := []byte("               Hello world!             ")
+	for i := 0; i < b.N; i++ {
+		_ = bytes.TrimSpace(s)
+	}
+}
+
+func BenchmarkUtilStdStringsTrimSpace(b *testing.B) {
+	s := "               Hello world!             "
+	for i := 0; i < b.N; i++ {
+		_ = strings.TrimSpace(s)
+	}
+}
+
+func BenchmarkUtilSeparateByComma(b *testing.B) {
+	s := "Hello,,World!,Enjoy"
+	for i := 0; i < b.N; i++ {
+		_ = separateByComma(s)
+	}
+}
+
+func BenchmarkUtilSeparateBySpace(b *testing.B) {
+	s := " Hello  World! Enjoy"
+	for i := 0; i < b.N; i++ {
+		_ = separateBySpace(s)
+	}
+}
+
+func BenchmarkUtilSeparateByAS(b *testing.B) {
+	s := "table.Name AS myTableAlias"
+	for i := 0; i < b.N; i++ {
+		_ = separateByAS(s)
+	}
+}
+
+func BenchmarkUtilSeparateByCommaRegExp(b *testing.B) {
+	sep := regexp.MustCompile(`\s*?,\s*?`)
+	s := "Hello,,World!,Enjoy"
+	for i := 0; i < b.N; i++ {
+		_ = sep.Split(s, -1)
+	}
+}
+
+func BenchmarkUtilSeparateBySpaceRegExp(b *testing.B) {
+	sep := regexp.MustCompile(`\s+`)
+	s := " Hello  World! Enjoy"
+	for i := 0; i < b.N; i++ {
+		_ = sep.Split(s, -1)
+	}
+}
+
+func BenchmarkUtilSeparateByASRegExp(b *testing.B) {
+	sep := regexp.MustCompile(`(?i:\s+AS\s+)`)
+	s := "table.Name AS myTableAlias"
+	for i := 0; i < b.N; i++ {
+		_ = sep.Split(s, -1)
+	}
+}