func (lsh *SqlLsh) Index() error {
	tx, err := lsh.db.Begin()
	if err != nil {
		return err
	}
	for i := range lsh.indexStmts {
		_, err = tx.Stmt(lsh.indexStmts[i]).Exec()
		if err != nil {
			tx.Rollback()
			return err
		}
	}
	err = tx.Commit()
	if err != nil {
		tx.Rollback()
		return err
	}
	return nil
}
Index builds l B-Tree multi-column indexes, each covers a
concatenated hash key.
This can improve the query performance of the LSH index.
package sqllsh
import (
	"database/sql"
	"errors"
	"fmt"
	"strings"
)
type Signature []uint
type SqlLsh struct {
	k              int               
	l              int               
	tableName      string            
	db             *sql.DB           
	varFmt         func(int) string  
	insertStmt     *sql.Stmt
	queryStmt      *sql.Stmt
	scanStmt       *sql.Stmt
	indexStmts     []*sql.Stmt
	createIndexFmt string
}
func newSqlLsh(k, l int, tableName string, db *sql.DB,
	varFmt func(int) string,
	createIndexFmt string) (*SqlLsh, error) {
	lsh := &SqlLsh{
		k:              k,
		l:              l,
		tableName:      tableName,
		db:             db,
		varFmt:         varFmt,
		createIndexFmt: createIndexFmt,
	}
	tx, err := db.Begin()
	if err != nil {
		return nil, err
	}
	_, err = tx.Exec(lsh.createTableStr())
	if err != nil {
		tx.Rollback()
		return nil, err
	}
	err = tx.Commit()
	if err != nil {
		tx.Rollback()
		return nil, err
	}
	lsh.insertStmt, err = lsh.createInsertStmt()
	if err != nil {
		return nil, err
	}
	lsh.queryStmt, err = lsh.createQueryStmt()
	if err != nil {
		return nil, err
	}
	lsh.scanStmt, err = lsh.createScanStmt()
	if err != nil {
		return nil, err
	}
	lsh.indexStmts, err = lsh.createIndexStmts()
	if err != nil {
		return nil, err
	}
	return lsh, nil
}