Skip to content

Оптимизация БД Сергеенков М.С. #19

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .rspec
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--require spec_helper
2 changes: 1 addition & 1 deletion .ruby-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.6.3
2.6.5
13 changes: 12 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
@@ -1,16 +1,27 @@
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby '2.6.3'
ruby '2.6.5'

gem 'rails', '~> 5.2.3'
gem 'pg', '>= 0.18', '< 2.0'
gem 'puma', '~> 3.11'
gem 'bootsnap', '>= 1.1.0', require: false
gem 'oj'
gem 'activerecord-import'

group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
gem 'rspec-rails'
gem 'factory_bot_rails'
gem 'faker'
gem 'rails-controller-testing'
gem 'capybara'
gem 'rspec-benchmark'
gem 'pghero'
gem 'pry'
gem 'rack-mini-profiler'
end

group :development do
Expand Down
81 changes: 79 additions & 2 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ GEM
activemodel (= 5.2.3)
activesupport (= 5.2.3)
arel (>= 9.0)
activerecord-import (1.0.4)
activerecord (>= 3.2)
activestorage (5.2.3)
actionpack (= 5.2.3)
activerecord (= 5.2.3)
Expand All @@ -42,15 +44,37 @@ GEM
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
addressable (2.7.0)
public_suffix (>= 2.0.2, < 5.0)
arel (9.0.0)
benchmark-malloc (0.1.0)
benchmark-perf (0.5.0)
benchmark-trend (0.3.0)
bindex (0.6.0)
bootsnap (1.4.2)
msgpack (~> 1.0)
builder (3.2.3)
byebug (11.0.1)
capybara (3.31.0)
addressable
mini_mime (>= 0.1.3)
nokogiri (~> 1.8)
rack (>= 1.6.0)
rack-test (>= 0.6.3)
regexp_parser (~> 1.5)
xpath (~> 3.2)
coderay (1.1.2)
concurrent-ruby (1.1.5)
crass (1.0.4)
diff-lcs (1.3)
erubi (1.8.0)
factory_bot (5.1.1)
activesupport (>= 4.2.0)
factory_bot_rails (5.1.1)
factory_bot (~> 5.1.0)
railties (>= 4.2.0)
faker (2.10.2)
i18n (>= 1.6, < 2)
ffi (1.10.0)
globalid (0.4.2)
activesupport (>= 4.2.0)
Expand All @@ -76,9 +100,18 @@ GEM
nio4r (2.3.1)
nokogiri (1.10.2)
mini_portile2 (~> 2.4.0)
oj (3.10.2)
pg (1.1.4)
pghero (2.4.1)
activerecord (>= 5)
pry (0.12.2)
coderay (~> 1.1.0)
method_source (~> 0.9.0)
public_suffix (4.0.3)
puma (3.12.1)
rack (2.0.6)
rack-mini-profiler (1.1.6)
rack (>= 1.2.0)
rack-test (1.1.0)
rack (>= 1.0, < 3)
rails (5.2.3)
Expand All @@ -94,6 +127,10 @@ GEM
bundler (>= 1.3.0)
railties (= 5.2.3)
sprockets-rails (>= 2.0.0)
rails-controller-testing (1.0.4)
actionpack (>= 5.0.1.x)
actionview (>= 5.0.1.x)
activesupport (>= 5.0.1.x)
rails-dom-testing (2.0.3)
activesupport (>= 4.2.0)
nokogiri (>= 1.6)
Expand All @@ -109,6 +146,33 @@ GEM
rb-fsevent (0.10.3)
rb-inotify (0.10.0)
ffi (~> 1.0)
regexp_parser (1.6.0)
rspec (3.9.0)
rspec-core (~> 3.9.0)
rspec-expectations (~> 3.9.0)
rspec-mocks (~> 3.9.0)
rspec-benchmark (0.5.1)
benchmark-malloc (~> 0.1.0)
benchmark-perf (~> 0.5.0)
benchmark-trend (~> 0.3.0)
rspec (>= 3.0.0, < 4.0.0)
rspec-core (3.9.1)
rspec-support (~> 3.9.1)
rspec-expectations (3.9.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.9.0)
rspec-mocks (3.9.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.9.0)
rspec-rails (3.9.0)
actionpack (>= 3.0)
activesupport (>= 3.0)
railties (>= 3.0)
rspec-core (~> 3.9.0)
rspec-expectations (~> 3.9.0)
rspec-mocks (~> 3.9.0)
rspec-support (~> 3.9.0)
rspec-support (3.9.2)
ruby_dep (1.5.0)
sprockets (3.7.2)
concurrent-ruby (~> 1.0)
Expand All @@ -129,22 +193,35 @@ GEM
websocket-driver (0.7.0)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.3)
xpath (3.2.0)
nokogiri (~> 1.8)

PLATFORMS
ruby

DEPENDENCIES
activerecord-import
bootsnap (>= 1.1.0)
byebug
capybara
factory_bot_rails
faker
listen (>= 3.0.5, < 3.2)
oj
pg (>= 0.18, < 2.0)
pghero
pry
puma (~> 3.11)
rack-mini-profiler
rails (~> 5.2.3)
rails-controller-testing
rspec-benchmark
rspec-rails
tzinfo-data
web-console (>= 3.3.0)

RUBY VERSION
ruby 2.6.3p62
ruby 2.6.5p114

BUNDLED WITH
2.0.2
2.1.4
2 changes: 1 addition & 1 deletion app/controllers/trips_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ class TripsController < ApplicationController
def index
@from = City.find_by_name!(params[:from])
@to = City.find_by_name!(params[:to])
@trips = Trip.where(from: @from, to: @to).order(:start_time)
@trips = Trip.includes(bus: :services).where(from: @from, to: @to).order(:start_time)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

end
end
7 changes: 6 additions & 1 deletion app/models/bus.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,13 @@ class Bus < ApplicationRecord
].freeze

has_many :trips
has_and_belongs_to_many :services, join_table: :buses_services
has_many :buses_services
has_many :services, through: :buses_services
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


validates :number, presence: true, uniqueness: true
validates :model, inclusion: { in: MODELS }

def services_names
services.pluck(:name)
end
end
4 changes: 4 additions & 0 deletions app/models/buses_service.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class BusesService < ApplicationRecord
belongs_to :bus
belongs_to :service
end
3 changes: 2 additions & 1 deletion app/models/service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ class Service < ApplicationRecord
'Можно не печатать билет',
].freeze

has_and_belongs_to_many :buses, join_table: :buses_services
has_many :buses_services
has_many :buses, through: :buses_services

validates :name, presence: true
validates :name, inclusion: { in: SERVICES }
Expand Down
78 changes: 78 additions & 0 deletions app/services/reload_json.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
class ReloadJson
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Плюс за вынос логики в отдельный файл, но не очень понятное название.
Из названия непонятно что именно за json

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ага, поспешил(

class << self
def call(file_name)
new.call(file_name)
end
end

attr_reader :cities, :services, :buses, :trips

def initialize
@cities = {}
@services = {}
@buses = {}
@trips = []
end

def call(file_name)
json = Oj.load(File.read(file_name))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Так грузим сразу весь json в память, при большом файле потратим много оперативки, раздуем память процесса.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Точно...


ActiveRecord::Base.transaction do
Trip.delete_all
City.delete_all
BusesService.delete_all
Bus.delete_all
Service.delete_all

json.each do |trip|
from = find_or_create_city(trip['from'])
to = find_or_create_city(trip['to'])

bus_services = []

trip['bus']['services'].each do |service|
bus_services << find_or_create_service(service)
end

bus = find_or_create_bus(
trip['bus']['number'], trip['bus']['model'], bus_services
)

trips << {
from_id: from.id,
to_id: to.id,
bus_id: bus.id,
start_time: trip['start_time'],
duration_minutes: trip['duration_minutes'],
price_cents: trip['price_cents'],
}
end

Trip.import trips, batch_size: 1000
end
end

private

def find_or_create_city(name)
return cities[name] if cities.key?(name)

cities[name] = City.create(name: name)
end

def find_or_create_service(name)
return services[name] if services.key?(name)

services[name] = Service.create(name: name)
end

def find_or_create_bus(number, model, services)
return buses[number] if buses.key?(number)

buses[number] = Bus.create(
number: number,
model: model,
services: services
)
end
end
8 changes: 4 additions & 4 deletions app/views/trips/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
<%= "Автобусы #{@from.name} – #{@to.name}" %>
</h1>
<h2>
<%= "В расписании #{@trips.count} рейсов" %>
<%= "В расписании #{@trips.size} рейсов" %>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

</h2>

<% @trips.each do |trip| %>
<ul>
<%= render "trip", trip: trip %>
<% if trip.bus.services.present? %>
<%= render "services", services: trip.bus.services %>
<%= render trip %>
<% trip.bus.services_names.each do |name| %>
<li><%= "#{name}" %></li>
<% end %>
</ul>
<%= render "delimiter" %>
Expand Down
3 changes: 3 additions & 0 deletions config/database.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
default: &default
adapter: postgresql
encoding: unicode
username: postgres
password: 12345678
host: localhost
# For details on connection pooling, see Rails configuration guide
# http://guides.rubyonrails.org/configuring.html#database-pooling
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
Expand Down
2 changes: 2 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
get "/" => "statistics#index"
get "автобусы/:from/:to" => "trips#index"

mount PgHero::Engine, at: "pghero"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

end
15 changes: 15 additions & 0 deletions db/migrate/20200218193515_create_pghero_query_stats.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class CreatePgheroQueryStats < ActiveRecord::Migration[5.2]
def change
create_table :pghero_query_stats do |t|
t.text :database
t.text :user
t.text :query
t.integer :query_hash, limit: 8
t.float :total_time
t.integer :calls, limit: 8
t.timestamp :captured_at
end

add_index :pghero_query_stats, [:database, :captured_at]
end
end
13 changes: 13 additions & 0 deletions db/migrate/20200218193618_create_pghero_space_stats.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class CreatePgheroSpaceStats < ActiveRecord::Migration[5.2]
def change
create_table :pghero_space_stats do |t|
t.text :database
t.text :schema
t.text :relation
t.integer :size, limit: 8
t.timestamp :captured_at
end

add_index :pghero_space_stats, [:database, :captured_at]
end
end
5 changes: 5 additions & 0 deletions db/migrate/20200219193035_add_uniq_index_to_city_name.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddUniqIndexToCityName < ActiveRecord::Migration[5.2]
def change
add_index :cities, :name, unique: true
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

В данном случае не важно, но напоминаю про опцию concurrently

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ага, спасибо

end
end
5 changes: 5 additions & 0 deletions db/migrate/20200219193338_add_uniq_index_to_bus_number.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddUniqIndexToBusNumber < ActiveRecord::Migration[5.2]
def change
add_index :buses, :number, unique: true
end
end
5 changes: 5 additions & 0 deletions db/migrate/20200219193829_add_uniq_index_to_service_name.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddUniqIndexToServiceName < ActiveRecord::Migration[5.2]
def change
add_index :services, :name, unique: true
end
end
Loading