Create a read-only user on Postgres

For development purposes, we need to create a read-only user and read-write user for Postgres databases. We can create a separate role for those two types of user and assigned them in the specific role.

Here is step by step command to do that.

Create a new role with read-only permission:

-- Create read-only role
CREATE ROLE ro;

-- Grant access to existing tables
GRANT USAGE ON SCHEMA public TO ro;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO ro;
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA public TO ro;

-- Grant access to future tables
ALTER DEFAULT PRIVILEGES IN SCHEMA public 
GRANT SELECT ON TABLES TO ro;

-- Create a final user with password
CREATE USER ro_user WITH PASSWORD '*********';
GRANT ro TO ro_user;

If you need to give access other schemas rather then public just replace the schema name with the public:

GRANT USAGE ON schema otherschema TO ro;

GRANT SELECT ON ALL TABLES IN SCHEMA otherschema TO ro_user;

GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA otherschema TO ro_user;

 

Data Engineer কারা ? তাদের কাজ আসলে কি ?

অনেকের মনে প্রশ্ন থাকে Data Engineering আসলে কি ? Data Engineer দের কাজ আসলে কি ? কি কি স্কিল থাকতে হয় ?

Data Engineering হলো Data Analysis করার আগের ধাপ। Data Engineer দের প্রধান কাজ হলো বিম্ভিন্ন জায়গা থেকে Data কালেক্ট করা, সেগুলো ক্লিন করা এবং Data Storage এর মধ্যে রাখা ।

ধরা যাক ABC কোম্পানির সার্ভিস হলো IOT ডিভাইস দিয়ে গাড়ি ট্রাক করা । কোনো ইউজার যদি যাদের সার্ভিস নেয় তাহলে তারা একটি ডিভাইস তাদের গাড়িতে লাগাবে এবং ইউজার একটি মোবাইল এপ এর সাহায্যে গাড়ির অবস্থান কোথায়, ফুয়েল কতো খরচ হলো , কত কিলোমিটার গাড়ি চলেছে ইত্যাদি তথ্য দেখতে পারবে । সম্পূর্ণ সিস্টেমটি চলতে একটি IOT ডিভাইস লাগবে যেখান থেকে প্রতি ৫ মিনিট পর পর গাড়ির তথ্য সার্ভার এ পাঠাতে হবে। ধরে নিলাম IOT ডিভাইস ইন্টারনেট এর মাধ্যেমে কানেক্টেড। এই তথ্য গুলি এক বা একাধিক ডাটাবেজ এ জমা হয় । এছাড়াও IOT ডিভাইস এবং ইউজারদের মোবাইল এপ এর ইভেন্ট লগ আরেকটি ডাটাবেজ এ রাখা হয় বিভিন্ন Analytics বের করার জন্য।

ABC কোম্পানির একটা মার্কেটিং টিম আছে, যাদের কাজ হলো তারা গাড়ীর মালিকদের কাছে যাবে এবং প্রডাক্ট সম্পর্কে জানাবে, যদি সব কিছু ঠিক থাকে এবং ইউজারদের পছন্দ হয় তাহলে তারা বাৎসরিক একটা সাবস্ক্রিপশন কিনবে। মার্কেটিং এবং সেলস টিম তাদের তথ্য Third Party কোনো সফটওয়ার ব্যাবহার করে। আবার কাস্টোমারদের পেমেন্ট এর তথ্য প্রডাক্ট এর ডাটাবেজ এই রাখা হয়।

উপরের ইউজ কেস এ আমরা দেখতে পাচ্ছি বিভিন্ন জায়গা থেকে রিয়াল টাইম এবং সেলস এর তথ্য বিভিন্ন ডাটাবেজ সার্ভার এ জমা হচ্ছে। Data Engineer দের কাজ হলো এই সব ডেটা সোর্স থেকে ডেটা একটা নির্দিষ্ট ডাটাবেজ স্টোরেজ এ নিয়ে আসা এবং পরবর্তীতে analysis এ ব্যাবহার করা ।

সুতরাং Data Engineer দের প্রধান কাজ হলো –
১। Data Analytics এর জন্য আর্কিটেকচার ডেভেলপ এবং মেইন্টেইন করা ( কি ধরনের ডেটাবেজ ব্যাবহার করা হবে, ডেটা প্রসেসিং কীভাবে হবে ) ।
২। Data Pipeline ডিজাইন করা। Data Pipeline বলতে এক বা একাধিক সোর্স থেকে ডেটা কি লজিক এ আসবে, কিভাবে সেগুলো ক্লিন করা হবে এবং কিভাবে স্টোর হবে সেটা ডিজাইন করা।
৩। প্রসেস Data অন্য টিমকে দেবার জন্য API ডিজাইন করা।
৪। ১০০% নিশ্চিত করা সব Data Pipeline প্রতিদিন/ দিনে কয়েকবার স্বয়ংক্রিয় ভাবে চলেছে কিনা।
৫। ১০০% ভাগ নিশয়তা দেয়া প্রসেস Data সঠিক কারন এই Data থেকেই পরবর্তী বিজনেস ডিসিশন নেয়া হয়ে থাকে।

Data engineer হতে গেলে এই স্কিলসেট গুলি দরকার –
১। Distributed system এর আর্কিটেকচার সম্পর্কে ভালো ধারনা থাকতে হবে এবং Distributed system ডিজাইন করতে হবে।
২। রিলায়েবল Data পাইপলাইন ডিজাইন করতে হবে।
৩। বিভিন্ন Data সোর্স থেকে Data কালেক্ট করতে হবে ( Data ফরমেট xml , json , text , csv হতে পারে )
৪। বিভিন্ন Data storage সম্পর্কে ভালো ধারনা থাকতে হবে এবং উইজ কেস অনুযায়ী Data storage ডিজাইন করতে হবে।

সুতরাং কেউ যদি large-scale system ডিজাইন করতে আগ্রহী হন অথবা বিশাল পরিমান data নিয়ে কাজ করতে আগ্রহী হন তাহলে Data Engineering আপনার জন্য ভালো পেশা হতে পারে।

Finding Missing Index in PostgreSQL

For better query performance we need to analyze indexing in PostgreSQL tables. Postgres has some support to find out missing indexing in a table.

This query finds missing index in PostgreSQL:

SELECT
  relname,
  seq_scan - idx_scan AS too_much_seq,
  CASE
    WHEN seq_scan - coalesce(idx_scan, 0) > 0 THEN 'Missing Index ?'
    ELSE 'OK'
  END,
  pg_relation_size(relname::regclass) AS rel_size, 
  seq_scan, idx_scan
FROM pg_stat_all_tables

WHERE schemaname = 'public' AND pg_relation_size(relname::regclass) > 80000 
ORDER BY too_much_seq DESC;

Another helpful query to find which tables need indexing:

SELECT
  x1.table_in_trouble,
  pg_relation_size(x1.table_in_trouble) AS sz_n_byts,
  x1.seq_scan,
  x1.idx_scan,
  CASE
  WHEN pg_relation_size(x1.table_in_trouble) > 500000000
    THEN 'Exceeds 500 megs, too large to count in a view. For a count, count individually'::text
  ELSE count(x1.table_in_trouble)::text
  END                                   AS tbl_rec_count,
  x1.priority
FROM
  (
    SELECT
      (schemaname::text || '.'::text) || relname: :text AS table_in_trouble,
      seq_scan,
      idx_scan,
      CASE
      WHEN (seq_scan - idx_scan) < 500
        THEN 'Minor Problem'::text
      WHEN (seq_scan - idx_scan) >= 500 AND (seq_scan - idx_scan) < 2500
        THEN 'Major Problem'::text
      WHEN (seq_scan - idx_scan) >= 2500
        THEN 'Extreme Problem'::text
      ELSE NULL::text
      END AS priority
    FROM
      pg_stat_all_tables
    WHERE
      seq_scan > idx_scan
      AND schemaname != 'pg_catalog'::name
    AND seq_scan > 100) x1
GROUP BY
  x1.table_in_trouble,
  x1.seq_scan,
  x1.idx_scan,
  x1.priority
ORDER BY
  x1.priority DESC,
  x1.seq_scan;

Finding Slow Queries in PostgreSQL

As a data engineer sometimes we need to find which queries taking too much time. In postgreSQL there is a module called pg_stats_statements which  provide very good stats about slow queries. This module tracks execution statistics of SQL statements and helps to find slow performing queries.

To enable this fist we need to run

CREATE EXTENSION pg_stat_statements

Column and definition for pg_stats_statements:

Name Type References Description
userid oid pg_authid.oid OID of user who executed the statement
dbid oid pg_database.oid OID of database in which the statement was executed
queryid bigint Internal hash code, computed from the statement’s parse tree
query text Text of a representative statement
calls bigint Number of times executed
total_time double precision Total time spent in the statement, in milliseconds
min_time double precision Minimum time spent in the statement, in milliseconds
max_time double precision Maximum time spent in the statement, in milliseconds
mean_time double precision Mean time spent in the statement, in milliseconds
stddev_time double precision Population standard deviation of time spent in the statement, in milliseconds
rows bigint Total number of rows retrieved or affected by the statement
shared_blks_hit bigint Total number of shared block cache hits by the statement
shared_blks_read bigint Total number of shared blocks read by the statement
shared_blks_dirtied bigint Total number of shared blocks dirtied by the statement
shared_blks_written bigint Total number of shared blocks written by the statement
local_blks_hit bigint Total number of local block cache hits by the statement
local_blks_read bigint Total number of local blocks read by the statement
local_blks_dirtied bigint Total number of local blocks dirtied by the statement
local_blks_written bigint Total number of local blocks written by the statement
temp_blks_read bigint Total number of temp blocks read by the statement
temp_blks_written bigint Total number of temp blocks written by the statement
blk_read_time double precision Total time the statement spent reading blocks, in milliseconds (if track_io_timing is enabled, otherwise zero)
blk_write_time double precision Total time the statement spent writing blocks, in milliseconds (if track_io_timing is enabled, otherwise zero)

To find slow queries, you can run below SQL command:

SELECT * FROM pg_stat_statements ORDER BY total_time DESC;

Installing Ruby and Rails with rbenv in Fedora 27

Screenshot from 2018-03-09 03-51-01

The first step is to install dependencies for Ruby.

sudo dnf install git-core zlib zlib-devel gcc-c++ patch readline readline-devel libyaml-devel libffi-devel openssl-devel make bzip2 autoconf automake libtool bison curl sqlite-devel

Install rbenv

cd
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(rbenv init -)"' >> ~/.bashrc
exec $SHELL

git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
echo 'export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' >> ~/.bashrc
exec $SHELL

Install Ruby

rbenv install 2.5.0
rbenv global 2.5.0
ruby -v

Use this command if you do not want rubygems to install the documentation for each package locally.

echo "gem: --no-ri --no-rdoc" > ~/.gemrc

Install bundler

gem install bundler

Whenever you install a new version of Ruby or a gem, you should run the rehash sub-command. This will make rails executables known to rbenv, which will allow us to run those executables:

rbenv rehash 

Installing Rails

Rails depends on a Javascript runtime, install nodejs.

sudo dnf install epel-release
sudo dnf install nodejs

And now install Rails

gem install rails -v 5.1.5
rbenv rehash
rails -v

#Create your first Rails app

rails new myapp

# Move into the application directory
cd myapp

# Create the database
rake db:create

# Start the server
rails server

You can now visit http://localhost:3000 to view your new website.

Install different python versions with virtualenvwrapper

Sometimes we need to install different version of virtual environments in same machine.

Check this post for create virtual environment in Ubuntu 16.04.

First you need to install different python versions in your machine.

Ubuntu 14.04 and 16.04

If you are using Ubuntu 14.04 or 16.04, you can use J Fernyhough’s PPA:

sudo add-apt-repository ppa:jonathonf/python-3.6
sudo apt-get update
sudo apt-get install python3.6

Alternatively, you use Felix Krull’s deadsnakes PPA:

sudo add-apt-repository ppa:fkrull/deadsnakes
sudo apt-get update
sudo apt-get install python3.6
Ubuntu 16.10 and 17.04

If you are using Ubuntu 16.10 or 17.04, then Python 3.6 is in the universe repository, so you can just run

sudo apt-get update
sudo apt-get install python3.6

Then you need to create virtual environment with specific python environment.

mkvirtualenv -p /usr/bin/python3.6 python_3.6

This will install python 3.6 in your machine.

Happy Coding 🙂

Create virtual environment with virtualenvwrapper in windows

Suppose you need to work on three different projects project A, project B and project C. project A and project B need python 3 and some required libraries. But for project C you need python 2.7 and dependent libraries.

So best practice for this is to separate those project environments. For creating separate python virtual environment need to follow below steps:

Step 1: Install pip with this command:
python -m pip install -U pip

Step 2: Then install “virtualenvwrapper-win” package by using command (command can be executed windows power shell):

pip install virtualenvwrapper-win

Step 3: Create a new virtualenv environment by using command: mkvirtualenv python_3.5

Step 4: Activate the environment by using command:

workon < environment name> Continue reading Create virtual environment with virtualenvwrapper in windows

Create virtual environment with virtualenvwrapper in Ubuntu 16.04

Suppose you need to work on three different projects project A, project B and project C. project A and project B need python 3 and some required libraries. But for project C you need python 2.7 and dependent libraries.

So best practice for this is to seperate those project environemtns. To create virtual environment you can use below technique:

  1. Virtualenv: Virtualenv is a tool to create isolated Python environments.
  2. Virtualenvwrapper: While virtual environments certainly solve some big problems with package management, they’re not perfect. After creating a few environments, you’ll start to see that they create some problems of their own, most of which revolve around managing the environments themselves. To help with this, the virtualenvwrapper tool was created, which is just some wrapper scripts around the main virtualenv tool.A few of the more useful features of virtualenvwrapper are that it:- Organizes all of your virtual environments in one location;
    – Provides methods to help you easily create, delete, and copy environments; and,
    – Provides a single command to switch between environments
  3. Conda: Conda is a package manager application that quickly installs, runs, and updates packages and their dependencies. Conda is also an environment manager application. A conda environment is a directory that contains a specific collection of conda packages that you have installed.

Continue reading Create virtual environment with virtualenvwrapper in Ubuntu 16.04

Adding a radius search to your Ruby on Rails 5 application and PostgreSQL

Recently one of my project need to create a functionality for location based search. I choose PostgreSQL as database because I want to use some power of PostgreSQL.

So I want to create a functionality where I can send three param in a PostgreSQL and this database will return me location within this radius.  So I want to search what locations are within X meters of these coordinates.

Using PostgreSQL is lot easier.

First you need to enable some plugin for PostgreSQL.

  CREATE EXTENSION cube;
  CREATE EXTENSION earthdistance;

Now you can run query like:

SELECT \"franchises\".* FROM \"franchises\" WHERE (earth_box(ll_to_earth(40.810649, -73.598605), 2000) @> ll_to_earth(latitude, longitude))

You can also create a scope in rails model.

scope :within_radius, lambda {|latitude, longitude, metres| where("earth_box(ll_to_earth(?, ?), ?) @> ll_to_earth(latitude, longitude)", latitude, longitude, metres) }

And that’s it. You can call

  Franchise.within_radius(43.6422125, -79.3744256, 5000) 

and you’ll have a list of franchises within 5 km of NY.

Happy coding 🙂

Custom seed files in Ruby on Rails 5 project

For project purpose sometimes we need to create multiple seed files. We can do this by simple creating rake tasks in ruby on rails.

To create a rake task for multiple seed file you can use below code:

# lib/tasks/custom_seed.rake
namespace :db do
  namespace :seed do
    Dir[File.join(Rails.root, 'db', 'seeds', '*.rb')].each do |filename|
      task_name = File.basename(filename, '.rb').intern    
      task task_name => :environment do
        load(filename) if File.exist?(filename)
      end
    end
  end
end

Please save this code to lib/tasks/custom_seed.rake file

Now create a folder called seeds inside your db folder: db/seeds

Now you can run any seed file from this folder by simple running below command:

# Name of the file without the .rb extension 
rake db:seed:seed_file_name 

Happy Coding 🙂