<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Lydia</title>
    <description>The latest articles on Forem by Lydia (@lydzb123).</description>
    <link>https://forem.com/lydzb123</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F464792%2F9c2258a5-b760-48cc-9ede-43e5637dfe75.png</url>
      <title>Forem: Lydia</title>
      <link>https://forem.com/lydzb123</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/lydzb123"/>
    <language>en</language>
    <item>
      <title>Optimizing your Postgres queries and server for heavy traffic</title>
      <dc:creator>Lydia</dc:creator>
      <pubDate>Thu, 31 Dec 2020 09:49:03 +0000</pubDate>
      <link>https://forem.com/lydzb123/optimizing-your-postgres-queries-and-server-for-heavy-traffic-1ok1</link>
      <guid>https://forem.com/lydzb123/optimizing-your-postgres-queries-and-server-for-heavy-traffic-1ok1</guid>
      <description>&lt;h2&gt;
  
  
  Let's optimize your psql queries!
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Indexing:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;PostgreSQL automatically creates an index for all primary keys, but are your foreign keys automatically indexed? Nope! &lt;strong&gt;You will need to explicitly create these indexes for any foreign key target columns.&lt;/strong&gt; This is particularly useful when you have queries with innerjoins and you are wanting to reference different relationships amongst your tables.&lt;/p&gt;

&lt;p&gt;By default, Postgres uses &lt;strong&gt;B-Tree indexing&lt;/strong&gt;, or binary tree indexing, which is great for making sequence searches obsolte. Cutting down on execution times. You will most likely see a dramatic drop in execution times.&lt;/p&gt;

&lt;p&gt;When dealing with a smaller count of records, or rows, sequential lookups may be fine. But imagine, a table of 10 million records. A sequential lookup for record number 99999 will take much longer than searching for record number 1. *B-Tree indexing runs heavy on memory usage. So, avoid unnecessary indexes. Index only the targets you actually need.&lt;/p&gt;

&lt;p&gt;If your data can be organized in ranges, perhaps an option to consider is using &lt;strong&gt;Brin-indexing&lt;/strong&gt; to partition different ranges in your records. By comparison, Brin-indexing requires significantly less memory.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Use Analytics and Test Your Queries:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;If you take a look at your query execution times, which you can do by typing &lt;strong&gt;EXPLAIN ANALYZE&lt;/strong&gt; before your query statement, you can easily see the decrease in execution times when using proper indexing.&lt;/p&gt;

&lt;p&gt;Try it out! Write a query, and use EXPLAIN ANALYZE to see the difference in preparation and execution times with records from the front, middle, and end of your records. How does you query perform?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pg_stat_statements&lt;/strong&gt; is a built in feature for Postgres that lets you see averages, median, min, max, and other metrics for your queries. This is especially a powerful and useful tool when executing prepared statements. To make Pg_stat available for use, you must add it to the &lt;strong&gt;shared_preload_libraries&lt;/strong&gt; found in the postgres config_file. Here are some tips to help with the config:&lt;/p&gt;

&lt;p&gt;-To find your config_file, in terminal type:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;psql -U username(usually defaulted to postgres) 
-c 'SHOW config_file'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;-Open the config_file (postgresql.conf) and search for “shared_preload_libraries”. Follow the guide below. These changes will require a psql restart.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;shared_preload_libraries = 'pg_stat_statements'
pg_stat_statements.max = 10000
pg_stat_statements.track = all
shared_preload_libraries = 'auto_explain'
auto_explain.log_min_duration = 0
auto_explain.log_analyze = on
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Optimizing Query Statements:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Avoid unnecessary inner-joins. Compare writing your queries with joins and then without? How do the execution times compare?&lt;/p&gt;

&lt;p&gt;Be specific. Only select, or get back the data that you actually need. * The beloved Select * is great and all, but if you can be more specific in your request, it'll save you memory in the long run.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;What's a Query Plan?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;A query plan is a sequence of steps or A PLAN made by the database that will be executed to get data. A query plan is prepared every single time a new query is performed. When you use EXPLAIN ANALYZE, your query plan will be printed along with preparation and execution times.&lt;/p&gt;

&lt;p&gt;The Query Plan lists how many rows were traversed, what kind of scans your query is running(index or sequential), how many workers were planned and launched, any used loops or nested loops along with execution times.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Prepared Statements!&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You can create prepared statements, so after your first query, every consecutive one after will spend less preparation time, and just focus on executing an already existing query plan. &lt;strong&gt;Creating a prepared statement is useful for queries that you know will be repeated.&lt;/strong&gt; It is a more dynamic way to query, as Postgres will only have to read through the query string and create one query plan on the first execution, with subsequent queries solely focusing on executing not preparing.&lt;/p&gt;

&lt;p&gt;Here's an example of a prepared statement taken from the PostgreSQL Documentation:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PREPARE fooplan (int, text, bool, numeric) AS
INSERT INTO foo VALUES($1, $2, $3, $4);

EXECUTE fooplan(1, 'Hunter Valley', 't', 200.00);
EXECUTE fooplan(2, 'Death Valley', 'f', 600.00);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In it, a plan called 'fooplan' is created. Fooplan has parameters that are confined to the chosen datatypes. The dollarsign + integer is used as a variable name to represent those arguments. To use the prepared statement fooplan, the word EXECUTE and plan name is used and any arguments are inputted in the parens.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Utilize thy CPU.&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;How many cores does your machine have? Maybe you are running your database server on a toaster, I mean, a t2.micro instance... Your beloved machine will only have 1 core. If you have more cores, which you probably do haha, you can utilize parallel queries by setting the number of &lt;strong&gt;maximum workers&lt;/strong&gt;. This allows multiple queries to be performed simultaneously on different cores. WOOT!&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Please manage your connections.&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;How many concurrent connections to your database server do you have?&lt;/strong&gt; AKA, how many users will be simultaneously making requests which will be making connections to your database server?&lt;/p&gt;

&lt;p&gt;PostgreSQL uses a &lt;strong&gt;max_connections&lt;/strong&gt; setting to limit the number of connections and resources that are consumed by connections. The default is typically 100 connections, but you may want to consider increasing this number to allot for more concurrent users. Having too few connections can cause network errors when traffic is heavy.&lt;/p&gt;

</description>
      <category>postgres</category>
      <category>indexing</category>
      <category>query</category>
      <category>optimizations</category>
    </item>
    <item>
      <title>Scraping images for batch downloads</title>
      <dc:creator>Lydia</dc:creator>
      <pubDate>Thu, 31 Dec 2020 08:49:00 +0000</pubDate>
      <link>https://forem.com/lydzb123/scraping-images-for-batch-downloads-4a9</link>
      <guid>https://forem.com/lydzb123/scraping-images-for-batch-downloads-4a9</guid>
      <description>&lt;p&gt;To use existing image APIs, like &lt;a href="https://loremflickr.com/"&gt;LoremFlickr&lt;/a&gt; or &lt;a href="http://placeimg.com/"&gt;PlaceImg&lt;/a&gt;, you can run this for loop directly in your terminal:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#install wget if you don't already have it
brew install wget 

for i in {1..10} ; do wget 
https://loremflickr.com/g/630/340/dog -O dog-"$i".jpg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This will go to the url 10 times, and download the request response as a jpg image, renaming the file "dog" with the "index number" appended. (ie. dog1.jpg, dog2.jpg, etc.)&lt;/p&gt;

&lt;p&gt;Here's another resource by a &lt;br&gt;
loadenmb for bulk downloads using your shell.&lt;br&gt;
&lt;a href="https://gist.github.com/loadenmb/08203f3467965776caea6b44d6f88fe3"&gt;https://gist.github.com/loadenmb/08203f3467965776caea6b44d6f88fe3&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To scrape a whole page, you can go through Google DevTools to get a list of all image urls. I'm sure there are other ways to go about this, but this is the way I found. It was also quite fun to get more familiarized with the DevTools Network panel and filtering capabilities through it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;-Open dev tools&lt;br&gt;
-Select the Network panel&lt;br&gt;
-Click the funnel icon to enable filtering&lt;br&gt;
-Select Img to enable filter for images only&lt;br&gt;
-Click and highlight all the image urls you want&lt;br&gt;
-Copy urls into a text file&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If your txt file is formatted correctly(with a new url on each line), with wget you can run this code to download all the urls from that txt file. FYI you may need to convert those downloads into JPEGs afterwards, something that I ended up just doing through my Mac Finder.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wget -i yourtextfile.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Hopefully these tips can help someone out there :D Best of luck with your scraping!&lt;/p&gt;

</description>
      <category>scrape</category>
      <category>images</category>
      <category>devtools</category>
      <category>wget</category>
    </item>
  </channel>
</rss>
