pg_query_analyzer 0.0.2 → 0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +46 -21
- data/lib/pg_query_analyzer.rb +15 -5
- metadata +1 -2
data/README
CHANGED
@@ -1,42 +1,67 @@
|
|
1
1
|
== PostgreSQL Query Analyzer for Rails
|
2
2
|
|
3
|
-
Provides a PostgreSQL query analysis in your development logs.
|
3
|
+
Provides a PostgreSQL query analysis in your development logs.
|
4
4
|
|
5
|
+
This is useful for finding indexes that your database may benefit from. There
|
6
|
+
are alternatives available that guess which indexes may help and provide
|
7
|
+
example migrations, but I've found that performing a manual analysis using
|
8
|
+
tools like this typically leads to the best results.
|
5
9
|
|
6
|
-
== Installation
|
7
10
|
|
8
|
-
|
11
|
+
== Instructions
|
9
12
|
|
10
|
-
|
13
|
+
Install the gem:
|
14
|
+
sudo gem install pg_query_analyzer
|
11
15
|
|
16
|
+
Require it development (config/enviroments/development.rb):
|
12
17
|
config.gem "pg_query_analyzer"
|
13
18
|
|
19
|
+
You'll achieve the best results if you have your production database available
|
20
|
+
locally. If you're using Heroku (http://heroku.com) this means setting up your
|
21
|
+
development database to use PostgreSQL and running ("heroku db:pull").
|
14
22
|
|
15
|
-
|
23
|
+
Restart your server ("script/server" or "touch tmp/restart.txt") and tail your
|
24
|
+
development log ("tail -f -n 100 log/development.log") to see the results. Note
|
25
|
+
the "total runtime", "cost", and "actual time" data points to locate long
|
26
|
+
running queries, as you might see in the second example provided below.
|
16
27
|
|
17
|
-
|
28
|
+
Once you identify which queries are worth optimizing, you can generate and run
|
29
|
+
migrations to create the appropriate indexes, restart your server, and check
|
30
|
+
your logs to ensure that you're getting the results you expect. Once you're
|
31
|
+
finished, you can comment out or remove the config.gem call.
|
18
32
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
-> Hash Join (cost=3.90..8.00 rows=1 width=8)
|
24
|
-
Hash Cond: (groups.id = contracts.group_id)
|
25
|
-
-> Seq Scan on groups (cost=0.00..3.79 rows=79 width=4)
|
26
|
-
-> Hash (cost=3.89..3.89 rows=1 width=4)
|
27
|
-
-> Seq Scan on contracts (cost=0.00..3.89 rows=1 width=4)
|
28
|
-
Filter: (user_id = 8)
|
33
|
+
Read more about database indexes here:
|
34
|
+
http://www.therailsway.com/2006/11/21/tracks-part-4
|
35
|
+
http://blog.evanweaver.com/articles/2007/02/12/table-indexes-in-rails/
|
36
|
+
http://github.com/eladmeidar/rails_indexes
|
29
37
|
|
30
38
|
|
31
|
-
==
|
39
|
+
== Example One
|
32
40
|
|
33
|
-
|
41
|
+
User Load (2.5ms) SELECT * FROM "users" WHERE ("users"."id" = 2) LIMIT 1
|
42
|
+
Analyzing User Load Execution Time: 0.002899
|
34
43
|
|
35
|
-
|
44
|
+
Limit (cost=0.00..8.27 rows=1 width=3734) (actual time=0.012..0.012 rows=1 loops=1)
|
45
|
+
Output: id, login, posts_count, followings_count, followers_count, created_at, updated_at,...
|
46
|
+
-> Index Scan using users_pkey on users (cost=0.00..8.27 rows=1 width=3734) (actual time=0.011..0.011 rows=1 loops=1)
|
47
|
+
Output: id, login, posts_count, followings_count, followers_count, created_at, updated_at...
|
48
|
+
Index Cond: (id = 2)
|
49
|
+
Total runtime: 0.052 ms
|
36
50
|
|
37
|
-
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.explain_verbose = true
|
38
51
|
|
39
|
-
|
52
|
+
== Example Two
|
53
|
+
|
54
|
+
FeedItem Load (5.1ms) SELECT * FROM "feed_items" WHERE ("feed_items".user_id = 2) ORDER BY feed_items.post_created_at DESC
|
55
|
+
Analyzing FeedItem Load Execution Time: 0.014169
|
56
|
+
|
57
|
+
Sort (cost=248.49..249.21 rows=290 width=32) (actual time=1.870..1.895 rows=290 loops=1)
|
58
|
+
Output: id, user_id, post_id, poster_id, post_created_at, created_at
|
59
|
+
Sort Key: post_created_at
|
60
|
+
Sort Method: quicksort Memory: 47kB
|
61
|
+
-> Seq Scan on feed_items (cost=0.00..236.62 rows=290 width=32) (actual time=0.015..1.735 rows=290 loops=1)
|
62
|
+
Output: id, user_id, post_id, poster_id, post_created_at, created_at
|
63
|
+
Filter: (user_id = 2)
|
64
|
+
Total runtime: 1.948 ms
|
40
65
|
|
41
66
|
|
42
67
|
== Credits
|
data/lib/pg_query_analyzer.rb
CHANGED
@@ -1,13 +1,23 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
module ConnectionAdapters
|
3
3
|
class PostgreSQLAdapter < AbstractAdapter
|
4
|
-
|
4
|
+
|
5
|
+
@@analyzer_debug = 0..2
|
6
|
+
@@analyzer_warn = 3..7
|
5
7
|
|
6
|
-
|
7
|
-
|
8
|
+
def select_logger time_spent, log
|
9
|
+
case time_spent
|
10
|
+
when @@analyzer_debug then @logger.debug(log)
|
11
|
+
when @@analyzer_warn then @logger.warn(log)
|
12
|
+
else @logger.fatal(log)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# ANALYZE carries out the command and show the actual run times.
|
17
|
+
@@explain_analyze = true # use nil to disable
|
8
18
|
|
9
|
-
|
10
|
-
@@explain_verbose = nil
|
19
|
+
# VERBOSE shows the full plan tree, rather than a summary.
|
20
|
+
@@explain_verbose = true # use nil to disable
|
11
21
|
|
12
22
|
private
|
13
23
|
|