/go/cmd/query_analyzer/query_analyzer.go

https://gitlab.com/18runt88/vitess · Go · 119 lines · 104 code · 12 blank · 3 comment · 19 complexity · 82bb3c517e167320b33e5e2040664243 MD5 · raw file

  1. // Copyright 2014, Google Inc. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package main
  5. import (
  6. "bufio"
  7. "bytes"
  8. "flag"
  9. "fmt"
  10. "io"
  11. "os"
  12. "sort"
  13. log "github.com/golang/glog"
  14. "github.com/youtube/vitess/go/exit"
  15. "github.com/youtube/vitess/go/vt/sqlparser"
  16. )
  17. var (
  18. ignores = [][]byte{
  19. []byte("#"),
  20. []byte("/*"),
  21. []byte("SET"),
  22. []byte("use"),
  23. []byte("BEGIN"),
  24. []byte("COMMIT"),
  25. []byte("ROLLBACK"),
  26. }
  27. bindIndex = 0
  28. queries = make(map[string]int)
  29. )
  30. type stat struct {
  31. Query string
  32. Count int
  33. }
  34. type stats []stat
  35. func (a stats) Len() int { return len(a) }
  36. func (a stats) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
  37. func (a stats) Less(i, j int) bool { return a[i].Count > a[j].Count }
  38. func main() {
  39. defer exit.Recover()
  40. flag.Parse()
  41. for _, filename := range flag.Args() {
  42. fmt.Printf("processing: %s\n", filename)
  43. if err := processFile(filename); err != nil {
  44. log.Errorf("processFile error: %v", err)
  45. exit.Return(1)
  46. }
  47. }
  48. var stats = make(stats, 0, 128)
  49. for k, v := range queries {
  50. stats = append(stats, stat{Query: k, Count: v})
  51. }
  52. sort.Sort(stats)
  53. for _, s := range stats {
  54. fmt.Printf("%d: %s\n", s.Count, s.Query)
  55. }
  56. }
  57. func processFile(filename string) error {
  58. f, err := os.Open(filename)
  59. if err != nil {
  60. return err
  61. }
  62. r := bufio.NewReader(f)
  63. for {
  64. line, err := r.ReadBytes('\n')
  65. if err != nil {
  66. if err == io.EOF {
  67. break
  68. }
  69. return err
  70. }
  71. analyze(line)
  72. }
  73. return nil
  74. }
  75. func analyze(line []byte) {
  76. for _, ignore := range ignores {
  77. if bytes.HasPrefix(line, ignore) {
  78. return
  79. }
  80. }
  81. dml := string(bytes.TrimRight(line, "\n"))
  82. ast, err := sqlparser.Parse(dml)
  83. if err != nil {
  84. log.Errorf("Error parsing %s", dml)
  85. return
  86. }
  87. bindIndex = 0
  88. buf := sqlparser.NewTrackedBuffer(formatWithBind)
  89. buf.Myprintf("%v", ast)
  90. addQuery(buf.ParsedQuery().Query)
  91. }
  92. func formatWithBind(buf *sqlparser.TrackedBuffer, node sqlparser.SQLNode) {
  93. switch node := node.(type) {
  94. case sqlparser.StrVal, sqlparser.NumVal:
  95. buf.WriteArg(fmt.Sprintf(":v%d", bindIndex))
  96. bindIndex++
  97. default:
  98. node.Format(buf)
  99. }
  100. }
  101. func addQuery(query string) {
  102. count, ok := queries[query]
  103. if !ok {
  104. count = 0
  105. }
  106. queries[query] = count + 1
  107. }