hudsonbay

hudsonbay

Different ways to create indexes in Ecto

Hi, please. I have a question regarding migrations in Ecto. But maybe this more of a PostgreSQL question rather than an Elixir one.

I have a many-to-many relation between students and teachers. One student can have many teachers and the same teacher can have many students.

So, I’m basically defining my migration like this:

 def change do
    create table(:students_teachers, primary_key: false) do
      add :id, :binary_id, primary_key: true
      add :criteria, :integer, null: false

      add(:student_id, references(:students, on_delete: :delete_all, type: :binary_id),
        null: false
      )

      add(:teacher_id, references(:teachers, on_delete: :delete_all, type: :binary_id),
        null: false
      )
    end

    create index(:students_teachers, [:student_id])
    create index(:students_teachers, [:teacher_id])
  end

Ok, my doubt is about the last line of the code, the part where I define the indexes:

create index(:students_teachers, [:student_id])
create index(:students_teachers, [:teacher_id])

But if I do it this in a second way create index(:students_teachers, [:student_id, :teacher_id]) something is gonna change.

If I do a diff to the two \d students_teachers generated tables in PostgreSQL with the different types of migrations I will see that there are some changes.

This the output of my diff (which BTW only sees the difference in the index definition):

>     "students_teachers_student_id_index" btree (student_id)
>     "students_teachers_teacher_id_index" btree (teacher_id)
---
<     "students_teachers_student_id_teacher_id" btree (student_id, teacher_id)

So, my question is:
How do this two approaches change the way my data is related? What is the difference here? How do the teacher and the student are related according to the different ways I migrated the database?

Marked As Solved

cenotaph

cenotaph

Let’s focus on your SQL question first

Rule of thumb:

  • If you need to search and access the records individually by teacher_id OR student_id you should create two indexes individually. I assume this is 99% the use case for most tables.
  • If you ALWAYS fetch the records from that table by teacher_id AND student_id, you should create a composite index.

Nope, that was not my statement. My statement was SLOW SELECT on top 2.

For clarification, when I say SLOW it is relative to correct index scan. SQL storages are fast enough to make up for the missing time, it is not easy for us humans to grasp the gap of milliseconds, microseconds, nanoseconds.

But that nano, milliseconds add up to minutes, hours, days over millions, billions of queries, transactions.

Repo.preload is all related to your definition of relationships. As long as there is a foreign_key (relation) path for Ecto to figure out the relationship, it will load them for you, regardless of how slow or inefficient the relationship is.

Also Liked

cenotaph

cenotaph

Individual indexes on student_id and teacher_id fields

SELECT ..... WHERE student_id=1 => FAST SELECT
SELECT ..... WHERE teacher_id=1 => FAST SELECT

You would be telling Ecto to create a composite index

SELECT ..... WHERE student_id=1 => SLOW SELECT
SELECT ..... WHERE teacher_id=1 => SLOW SELECT
SELECT ..... WHERE student_id= AND teacher_id=1 => FAST SELECT

yurko

yurko

The first two queries are not that bad either, they’d still use indexes, especially the first one. Here’s some info about that:

yurko

yurko

If you want to simplify the answer and make it slow / fast, then with your index (student_id, teacher_id) it would be

SELECT ..... WHERE student_id=1 => FAST SELECT
SELECT ..... WHERE teacher_id=1 => SLOW SELECT
SELECT ..... WHERE student_id= AND teacher_id=1 => FAST SELECT

See the link in my above comment for more on the topic of how slow the second query would be (not that slow).

From the Postgres docs (PostgreSQL: Documentation: 9.6: Multicolumn Indexes):

A multicolumn B-tree index can be used with query conditions that involve any subset of the index’s columns, but the index is most efficient when there are constraints on the leading (leftmost) columns.

Where Next?

Popular in Questions Top

JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
sacepums
Hey guys. I'm new to elixir and im really stocked about it. But I ran into a bit of problem - I need to convert a date sting, for examp...
New
vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
qwerescape
Is there a way to get the call stack or stack trace at any point in the code? Not from exceptions, but an expression that returns how the...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
johnnyicon
Hi all, I've just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I'm trying to use Postg...
New

Other popular topics Top

Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID&lt;0.412.0&gt; terminating ** (Postgrex.Error) FATAL...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
axelson
This post is a wiki (feel free to hit the edit button near the bottom right of this post to add your own changes!) This post collects co...
239 45766 226
New
ycv005
I have followed this StackOverflow post to install the specific version of Erlang. And When I am running mix ecto.setup then getting fol...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
beno
I will often find my self writing things similar to: case some_value do nil -&gt; something() "" -&gt; something() _ -&gt; someth...
New
lucidguppy
I have a super simple question about elixir - how would I take a file like this foo bar baz and output a new file that enumerates th...
New
AstonJ
by Lance Halvorsen Elixir and Phoenix are generating tremendous excitement as an unbeatable platform for building modern web application...
460 27162 124
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New
magnetic
Hey :wave:t3: Elixir community, I’ve been learning Elixir, and working on some side projects. My editor of choice is VSCode, and althoug...
New

We're in Beta

About us Mission Statement