Alter 'Chain.address_to_internal_transactions' query

* The query was taking too long and one of the reasons was because it was performing a sub-query in the internal_transactions table to identify if the transaction had siblings.
This was made because for every parent transactions there is one equal internal_transaction, so this check was made to only show internal transactions that are different from the parent transaction.

* There is another way to check this that removes the need to perform a sub-query in the internal transactions table. We need to check the indexes >`0` for `type`=`call`.

* Also created new indexes to improve the 'where' match and the 'order by' clause.
pull/928/head
Amanda Sposito 6 years ago
parent 373248dbee
commit 5ee4df3714
  1. 16
      apps/block_scout_web/test/block_scout_web/features/viewing_addresses_test.exs
  2. 2
      apps/explorer/lib/explorer/chain.ex
  3. 8
      apps/explorer/lib/explorer/chain/internal_transaction.ex
  4. 21
      apps/explorer/priv/repo/migrations/20181017141409_add_index_to_internal_transaction_table.exs
  5. 56
      apps/explorer/test/explorer/chain_test.exs

@ -62,7 +62,7 @@ defmodule BlockScoutWeb.ViewingAddressesTest do
internal_transaction = internal_transaction =
insert( insert(
:internal_transaction_create, :internal_transaction_create,
index: 0, index: 1,
transaction: transaction, transaction: transaction,
from_address: address, from_address: address,
created_contract_address: contract created_contract_address: contract
@ -84,7 +84,7 @@ defmodule BlockScoutWeb.ViewingAddressesTest do
insert( insert(
:internal_transaction, :internal_transaction,
index: 0, index: 1,
transaction: transaction, transaction: transaction,
from_address: lincoln, from_address: lincoln,
to_address: contract, to_address: contract,
@ -95,7 +95,7 @@ defmodule BlockScoutWeb.ViewingAddressesTest do
internal_transaction = internal_transaction =
insert( insert(
:internal_transaction_create, :internal_transaction_create,
index: 1, index: 2,
transaction: transaction, transaction: transaction,
from_address: contract, from_address: contract,
created_contract_address: another_contract created_contract_address: another_contract
@ -198,7 +198,7 @@ defmodule BlockScoutWeb.ViewingAddressesTest do
|> insert( |> insert(
transaction: from_lincoln, transaction: from_lincoln,
from_address: lincoln, from_address: lincoln,
index: 0 index: 1
) )
|> with_contract_creation(contract_address) |> with_contract_creation(contract_address)
@ -225,9 +225,9 @@ defmodule BlockScoutWeb.ViewingAddressesTest do
transaction = transactions.from_lincoln transaction = transactions.from_lincoln
internal_transaction_lincoln_to_address = internal_transaction_lincoln_to_address =
insert(:internal_transaction, transaction: transaction, to_address: address, index: 0) insert(:internal_transaction, transaction: transaction, to_address: address, index: 1)
insert(:internal_transaction, transaction: transaction, from_address: address, index: 1) insert(:internal_transaction, transaction: transaction, from_address: address, index: 2)
{:ok, %{internal_transaction_lincoln_to_address: internal_transaction_lincoln_to_address}} {:ok, %{internal_transaction_lincoln_to_address: internal_transaction_lincoln_to_address}}
end end
@ -278,7 +278,7 @@ defmodule BlockScoutWeb.ViewingAddressesTest do
|> assert_has(AddressPage.internal_transactions(count: 2)) |> assert_has(AddressPage.internal_transactions(count: 2))
internal_transaction = internal_transaction =
insert(:internal_transaction, transaction: transaction, index: 0, from_address: addresses.lincoln) insert(:internal_transaction, transaction: transaction, index: 2, from_address: addresses.lincoln)
Notifier.handle_event({:chain_event, :internal_transactions, :realtime, [internal_transaction]}) Notifier.handle_event({:chain_event, :internal_transactions, :realtime, [internal_transaction]})
@ -307,7 +307,7 @@ defmodule BlockScoutWeb.ViewingAddressesTest do
|> insert( |> insert(
transaction: from_lincoln, transaction: from_lincoln,
from_address: lincoln, from_address: lincoln,
index: 0 index: 1
) )
|> with_contract_creation(contract_address) |> with_contract_creation(contract_address)

@ -123,7 +123,7 @@ defmodule Explorer.Chain do
InternalTransaction InternalTransaction
|> InternalTransaction.where_address_fields_match(hash, direction) |> InternalTransaction.where_address_fields_match(hash, direction)
|> where_transaction_has_multiple_internal_transactions() |> InternalTransaction.where_is_different_from_parent_transaction()
|> page_internal_transaction(paging_options) |> page_internal_transaction(paging_options)
|> limit(^paging_options.page_size) |> limit(^paging_options.page_size)
|> order_by( |> order_by(

@ -468,4 +468,12 @@ defmodule Explorer.Chain.InternalTransaction do
it.created_contract_address_hash == ^address_hash it.created_contract_address_hash == ^address_hash
) )
end end
def where_is_different_from_parent_transaction(query) do
where(
query,
[it],
(it.type == ^:call and it.index > 0) or it.type != ^:call
)
end
end end

@ -1,7 +1,7 @@
defmodule Explorer.Repo.Migrations.AddIndexToInternalTransactionTable do defmodule Explorer.Repo.Migrations.AddIndexToInternalTransactionTable do
use Ecto.Migration use Ecto.Migration
def up do def change do
create( create(
index("internal_transactions", [ index("internal_transactions", [
:to_address_hash, :to_address_hash,
@ -12,23 +12,6 @@ defmodule Explorer.Repo.Migrations.AddIndexToInternalTransactionTable do
]) ])
) )
execute(""" create(index(:internal_transactions, ["block_number DESC, transaction_index DESC, index DESC"]))
CREATE INDEX itx_transactions_block_number_tx_index_index
ON internal_transactions (block_number DESC, transaction_index DESC, "index" DESC);
""")
end
def down do
drop(
index("internal_transactions", [
:to_address_hash,
:from_address_hash,
:created_contract_address_hash,
:type,
:index
])
)
execute("DROP INDEX itx_transactions_block_number_tx_index_index;")
end end
end end

@ -1266,7 +1266,7 @@ defmodule Explorer.ChainTest do
%InternalTransaction{id: first_id} = %InternalTransaction{id: first_id} =
insert(:internal_transaction, insert(:internal_transaction,
index: 0, index: 1,
transaction: transaction, transaction: transaction,
to_address: address, to_address: address,
block_number: transaction.block_number, block_number: transaction.block_number,
@ -1275,14 +1275,18 @@ defmodule Explorer.ChainTest do
%InternalTransaction{id: second_id} = %InternalTransaction{id: second_id} =
insert(:internal_transaction, insert(:internal_transaction,
index: 1, index: 2,
transaction: transaction, transaction: transaction,
to_address: address, to_address: address,
block_number: transaction.block_number, block_number: transaction.block_number,
transaction_index: transaction.index transaction_index: transaction.index
) )
result = address |> Chain.address_to_internal_transactions() |> Enum.map(& &1.id) result =
address
|> Chain.address_to_internal_transactions()
|> Enum.map(& &1.id)
assert Enum.member?(result, first_id) assert Enum.member?(result, first_id)
assert Enum.member?(result, second_id) assert Enum.member?(result, second_id)
end end
@ -1433,15 +1437,9 @@ defmodule Explorer.ChainTest do
:internal_transaction, :internal_transaction,
transaction: first_b_transaction, transaction: first_b_transaction,
to_address: address, to_address: address,
<<<<<<< HEAD
index: 1,
transaction_index: first_b_transaction.index,
block_number: first_b_transaction.block_number
=======
index: 2, index: 2,
block_number: first_b_transaction.block_number, block_number: first_b_transaction.block_number,
transaction_index: first_b_transaction.index transaction_index: first_b_transaction.index
>>>>>>> c06b04ad... fixup! Add 'block_number' and 'transaction_index' in 'internal_transaction'
) )
result = result =
@ -1461,24 +1459,14 @@ defmodule Explorer.ChainTest do
:internal_transaction, :internal_transaction,
transaction: pending_transaction, transaction: pending_transaction,
to_address: address, to_address: address,
<<<<<<< HEAD index: 1
index: 0,
transaction_index: pending_transaction.index
=======
index: 1,
>>>>>>> c06b04ad... fixup! Add 'block_number' and 'transaction_index' in 'internal_transaction'
) )
insert( insert(
:internal_transaction, :internal_transaction,
transaction: pending_transaction, transaction: pending_transaction,
to_address: address, to_address: address,
<<<<<<< HEAD index: 2
index: 1,
transaction_index: pending_transaction.index
=======
index: 2,
>>>>>>> c06b04ad... fixup! Add 'block_number' and 'transaction_index' in 'internal_transaction'
) )
a_block = insert(:block, number: 2000) a_block = insert(:block, number: 2000)
@ -1493,15 +1481,9 @@ defmodule Explorer.ChainTest do
:internal_transaction, :internal_transaction,
transaction: first_a_transaction, transaction: first_a_transaction,
to_address: address, to_address: address,
<<<<<<< HEAD
index: 0,
transaction_index: first_a_transaction.index,
block_number: first_a_transaction.block_number
=======
index: 1, index: 1,
block_number: first_a_transaction.block_number, block_number: first_a_transaction.block_number,
transaction_index: first_a_transaction.index transaction_index: first_a_transaction.index
>>>>>>> c06b04ad... fixup! Add 'block_number' and 'transaction_index' in 'internal_transaction'
) )
%InternalTransaction{id: second} = %InternalTransaction{id: second} =
@ -1509,15 +1491,9 @@ defmodule Explorer.ChainTest do
:internal_transaction, :internal_transaction,
transaction: first_a_transaction, transaction: first_a_transaction,
to_address: address, to_address: address,
<<<<<<< HEAD
index: 1,
transaction_index: first_a_transaction.index,
block_number: first_a_transaction.block_number
=======
index: 2, index: 2,
block_number: first_a_transaction.block_number, block_number: first_a_transaction.block_number,
transaction_index: first_a_transaction.index transaction_index: first_a_transaction.index
>>>>>>> c06b04ad... fixup! Add 'block_number' and 'transaction_index' in 'internal_transaction'
) )
second_a_transaction = second_a_transaction =
@ -1530,15 +1506,9 @@ defmodule Explorer.ChainTest do
:internal_transaction, :internal_transaction,
transaction: second_a_transaction, transaction: second_a_transaction,
to_address: address, to_address: address,
<<<<<<< HEAD
index: 0,
transaction_index: second_a_transaction.index,
block_number: second_a_transaction.block_number
=======
index: 1, index: 1,
block_number: second_a_transaction.block_number, block_number: second_a_transaction.block_number,
transaction_index: second_a_transaction.index transaction_index: second_a_transaction.index
>>>>>>> c06b04ad... fixup! Add 'block_number' and 'transaction_index' in 'internal_transaction'
) )
%InternalTransaction{id: fourth} = %InternalTransaction{id: fourth} =
@ -1546,15 +1516,9 @@ defmodule Explorer.ChainTest do
:internal_transaction, :internal_transaction,
transaction: second_a_transaction, transaction: second_a_transaction,
to_address: address, to_address: address,
<<<<<<< HEAD
index: 1,
transaction_index: second_a_transaction.index,
block_number: second_a_transaction.block_number
=======
index: 2, index: 2,
block_number: second_a_transaction.block_number, block_number: second_a_transaction.block_number,
transaction_index: second_a_transaction.index transaction_index: second_a_transaction.index
>>>>>>> c06b04ad... fixup! Add 'block_number' and 'transaction_index' in 'internal_transaction'
) )
b_block = insert(:block, number: 6000) b_block = insert(:block, number: 6000)
@ -1594,7 +1558,7 @@ defmodule Explorer.ChainTest do
|> Enum.map(& &1.id) |> Enum.map(& &1.id)
# block number ==, transaction index ==, internal transaction index < # block number ==, transaction index ==, internal transaction index <
assert [fifth, fourth, third, second, first] == assert [fourth, third, second, first] ==
address address
|> Chain.address_to_internal_transactions( |> Chain.address_to_internal_transactions(
paging_options: %PagingOptions{key: {6000, 0, 1}, page_size: 8} paging_options: %PagingOptions{key: {6000, 0, 1}, page_size: 8}

Loading…
Cancel
Save