From d603b293d88abb0a44e033d82c3b8f8724af0ee6 Mon Sep 17 00:00:00 2001 From: Allisson Azevedo Date: Thu, 14 Jun 2018 16:10:59 -0300 Subject: [PATCH 1/5] Add EstimatedTableRowsCount to avoid count in large tables --- pkg/client/client.go | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/pkg/client/client.go b/pkg/client/client.go index 0e826ff..5aad9b8 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -221,12 +221,35 @@ func (client *Client) TableRows(table string, opts RowsOptions) (*Result, error) return client.query(sql) } +func (client *Client) EstimatedTableRowsCount(table string, opts RowsOptions) (*Result, error) { + sql := fmt.Sprintf(`SELECT reltuples FROM pg_class WHERE relname = '%s'`, table) + + result, err := client.query(sql) + if err != nil { + return nil, err + } + // float64 to int64 conversion + estimatedRowsCount := result.Rows[0][0].(float64) + result.Rows[0] = Row{int64(estimatedRowsCount)} + + return result, nil +} + func (client *Client) TableRowsCount(table string, opts RowsOptions) (*Result, error) { schema, table := getSchemaAndTable(table) sql := fmt.Sprintf(`SELECT COUNT(1) FROM "%s"."%s"`, schema, table) if opts.Where != "" { sql += fmt.Sprintf(" WHERE %s", opts.Where) + } else { + tableInfo, err := client.TableInfo(table) + if err != nil { + return nil, err + } + estimatedRowsCount := tableInfo.Rows[0][3].(float64) + if estimatedRowsCount > 100000 { + return client.EstimatedTableRowsCount(table, opts) + } } return client.query(sql) From 8748f071673fcc4af8babcbd29308846b8c3b65c Mon Sep 17 00:00:00 2001 From: Allisson Azevedo Date: Thu, 14 Jun 2018 16:36:22 -0300 Subject: [PATCH 2/5] Use EstimatedTableRowsCount only for postgresql --- pkg/client/client.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/client/client.go b/pkg/client/client.go index 5aad9b8..cc28854 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -241,7 +241,7 @@ func (client *Client) TableRowsCount(table string, opts RowsOptions) (*Result, e if opts.Where != "" { sql += fmt.Sprintf(" WHERE %s", opts.Where) - } else { + } else if client.serverType == postgresType { tableInfo, err := client.TableInfo(table) if err != nil { return nil, err From 5ba53d3cbd9122d015db5ab657d6971d2951d60f Mon Sep 17 00:00:00 2001 From: Allisson Azevedo Date: Thu, 14 Jun 2018 17:51:16 -0300 Subject: [PATCH 3/5] Add test_EstimatedTableRowsCount --- pkg/client/client_test.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pkg/client/client_test.go b/pkg/client/client_test.go index 22f3416..c3d7647 100644 --- a/pkg/client/client_test.go +++ b/pkg/client/client_test.go @@ -278,6 +278,15 @@ func test_TableInfo(t *testing.T) { assert.Equal(t, 1, len(res.Rows)) } +func test_EstimatedTableRowsCount(t *testing.T) { + res, err := testClient.EstimatedTableRowsCount("books", RowsOptions{}) + + assert.Equal(t, nil, err) + assert.Equal(t, []string{"reltuples"}, res.Columns) + var count int64 = 15 + assert.Equal(t, []Row{Row{count}}, res.Rows) +} + func test_TableIndexes(t *testing.T) { res, err := testClient.TableIndexes("books") @@ -400,6 +409,7 @@ func TestAll(t *testing.T) { test_Table(t) test_TableRows(t) test_TableInfo(t) + test_EstimatedTableRowsCount(t) test_TableIndexes(t) test_TableConstraints(t) test_Query(t) From 974570c79e0ea498e3d257c86b39e43fd574af62 Mon Sep 17 00:00:00 2001 From: Allisson Azevedo Date: Sat, 16 Jun 2018 11:09:37 -0300 Subject: [PATCH 4/5] Add more tests --- pkg/client/client_test.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/pkg/client/client_test.go b/pkg/client/client_test.go index c3d7647..2f5014d 100644 --- a/pkg/client/client_test.go +++ b/pkg/client/client_test.go @@ -279,11 +279,31 @@ func test_TableInfo(t *testing.T) { } func test_EstimatedTableRowsCount(t *testing.T) { + var count int64 = 15 res, err := testClient.EstimatedTableRowsCount("books", RowsOptions{}) assert.Equal(t, nil, err) assert.Equal(t, []string{"reltuples"}, res.Columns) + assert.Equal(t, []Row{Row{count}}, res.Rows) +} + +func test_TableRowsCount(t *testing.T) { var count int64 = 15 + res, err := testClient.TableRowsCount("books", RowsOptions{}) + + assert.Equal(t, nil, err) + assert.Equal(t, []string{"count"}, res.Columns) + assert.Equal(t, []Row{Row{count}}, res.Rows) +} + +func test_TableRowsCountWithLargeTable(t *testing.T) { + var count int64 = 100010 + testClient.db.MustExec(`create table large_table as select s from generate_Series(1,100010) s;`) + testClient.db.MustExec(`VACUUM large_table;`) + res, err := testClient.TableRowsCount("large_table", RowsOptions{}) + + assert.Equal(t, nil, err) + assert.Equal(t, []string{"reltuples"}, res.Columns) assert.Equal(t, []Row{Row{count}}, res.Rows) } @@ -410,6 +430,8 @@ func TestAll(t *testing.T) { test_TableRows(t) test_TableInfo(t) test_EstimatedTableRowsCount(t) + test_TableRowsCount(t) + test_TableRowsCountWithLargeTable(t) test_TableIndexes(t) test_TableConstraints(t) test_Query(t) From 808f6eea33d1a1839496f6c834198dd8a7349f5a Mon Sep 17 00:00:00 2001 From: Allisson Azevedo Date: Sat, 16 Jun 2018 18:12:11 -0300 Subject: [PATCH 5/5] Change EstimatedTableRowsCount query --- pkg/client/client.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/client/client.go b/pkg/client/client.go index cc28854..5e7350a 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -222,7 +222,8 @@ func (client *Client) TableRows(table string, opts RowsOptions) (*Result, error) } func (client *Client) EstimatedTableRowsCount(table string, opts RowsOptions) (*Result, error) { - sql := fmt.Sprintf(`SELECT reltuples FROM pg_class WHERE relname = '%s'`, table) + schema, table := getSchemaAndTable(table) + sql := fmt.Sprintf(`SELECT reltuples FROM pg_class WHERE oid = '%s.%s'::regclass;`, schema, table) result, err := client.query(sql) if err != nil {