Skip to content

Commit

Permalink
Merge pull request #243 from decentraland/fix/several-queries
Browse files Browse the repository at this point in the history
feat: fix several queries having issues with performance
  • Loading branch information
juanmahidalgo authored Jan 16, 2025
2 parents 29829e7 + 2135486 commit 04343b3
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 22 deletions.
36 changes: 30 additions & 6 deletions src/ports/catalog/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,28 @@ const getLatestMetadataJoin = (filters: CatalogQueryFilters) => {

const getLatestMetadataCTE = () => {
return SQL`latest_metadata AS (
SELECT DISTINCT ON (wearable_id) wearable_id as item_id, id AS latest_metadata_id, item_type, wearable_id, emote_id
FROM `.append(MARKETPLACE_SQUID_SCHEMA).append(SQL`.metadata
ORDER BY wearable_id DESC
SELECT DISTINCT ON (wearable_id)
CASE
WHEN m.network = 'ETHEREUM'
THEN w.collection || '-' || m.id -- Use collection + '-' + metadata.id for L1 items
ELSE m.wearable_id::text
END AS item_id,
m.id AS latest_metadata_id,
m.item_type,
m.wearable_id,
m.emote_id
FROM
`
.append(MARKETPLACE_SQUID_SCHEMA)
.append(
SQL`.metadata as m
JOIN `.append(MARKETPLACE_SQUID_SCHEMA).append(SQL`.wearable AS w
ON w.id = m.wearable_id
ORDER BY
wearable_id DESC
)
`)
)
}

const getSearchCTEs = (filters: CatalogQueryFilters) => {
Expand Down Expand Up @@ -642,7 +659,14 @@ export const getCollectionsItemsCatalogQueryWithTrades = (filters: CatalogQueryF
items.network,
offchain_orders.open_item_trade_id,
offchain_orders.open_item_trade_price,
LEAST(items.first_listed_at, ROUND(EXTRACT(EPOCH FROM offchain_orders.min_item_created_at))) as first_listed_at,
`
.append(
filters.isOnSale // When filtering for NOT on sale, calculating this from the offchain orders is very expensive, we just avoid it
? SQL`LEAST(items.first_listed_at, ROUND(EXTRACT(EPOCH FROM offchain_orders.min_item_created_at))) as first_listed_at,`
: SQL`items.first_listed_at as first_listed_at,`
)
.append(
SQL`
items.urn,
CASE
WHEN offchain_orders.min_order_amount_received IS NULL AND nfts_with_orders.min_price IS NULL THEN NULL
Expand All @@ -661,7 +685,7 @@ export const getCollectionsItemsCatalogQueryWithTrades = (filters: CatalogQueryF
ROUND(EXTRACT(EPOCH FROM offchain_orders.max_created_at)),
nfts_with_orders.max_order_created_at
) AS max_order_created_at,`

)
.append(filters.isOnSale === false ? SQL`nfts.owners_count,` : SQL``)
.append(
`
Expand Down Expand Up @@ -697,7 +721,7 @@ export const getCollectionsItemsCatalogQueryWithTrades = (filters: CatalogQueryF
JOIN `.append(MARKETPLACE_SQUID_SCHEMA).append(SQL`.nft ON orders.nft_id = nft.id
WHERE
orders.status = 'open'
AND orders.expires_at_normalized > NOW() AND nft.owner_address = orders.owner`)
AND orders.expires_at_normalized > NOW()`)
)
.append(getOrderRangePriceWhere(filters))
.append(
Expand Down
8 changes: 3 additions & 5 deletions src/ports/nfts/ensQueries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,9 @@ function geENSWhereStatement(nftFilters: GetNFTsFilters): SQLStatement {
return SQL``
}

// Keep only filters that need JOINed tables
const FILTER_BY_OWNER = nftFilters.owner
? SQL` nft.owner_id IN (SELECT id FROM squid_marketplace.account WHERE address = ${nftFilters.owner.toLocaleLowerCase()}) `
: null
const ownerEthereumAddress = nftFilters.owner ? `${nftFilters.owner.toLocaleLowerCase()}-ETHEREUM` : null
const FILTER_BY_OWNER = nftFilters.owner ? SQL` owner_id = ${ownerEthereumAddress}` : null

const FILTER_BY_TOKEN_ID = nftFilters.tokenId ? SQL` token_id = ${nftFilters.tokenId} ` : null
const FILTER_BY_SEARCH = nftFilters.search ? SQL` search_text % ${nftFilters.search} ` : null
const FILTER_BY_IDS = nftFilters.ids?.length ? SQL` id = ANY (${nftFilters.ids}) ` : null
Expand Down Expand Up @@ -41,7 +40,6 @@ export function getENSs(nftFilters: GetNFTsFilters): SQLStatement {
.append(ids ? SQL` AND id = ANY(${ids}) ` : SQL``)
.append(
SQL`
ORDER BY created_at
)
`
.append(getTradesCTE(nftFilters, false))
Expand Down
6 changes: 4 additions & 2 deletions src/ports/nfts/landQueries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,13 @@ function getAllLANDWheres(filters: GetNFTsFilters & { rentalAssetsIds?: string[]
search,
rentalAssetsIds
} = filters
const ownerEthereumAddress = owner ? `${owner.toLocaleLowerCase()}-ETHEREUM` : null
const ownerPolygonAddress = owner ? `${owner.toLocaleLowerCase()}-POLYGON` : null
const FILTER_BY_OWNER =
owner && rentalAssetsIds?.length
? SQL` (nft.owner_id IN (SELECT id FROM squid_marketplace.account WHERE address = ${owner.toLowerCase()}) OR nft.id = ANY(${rentalAssetsIds})) `
? SQL` ((nft.owner_id = ${ownerEthereumAddress} OR nft.owner_id = ${ownerPolygonAddress}) OR nft.id = ANY(${rentalAssetsIds})) `
: owner && !rentalAssetsIds?.length
? SQL` nft.owner_id IN (SELECT id FROM squid_marketplace.account WHERE address = ${owner.toLowerCase()}) `
? SQL` (nft.owner_id = ${ownerEthereumAddress} OR nft.owner_id = ${ownerPolygonAddress}) `
: null
const FILTER_BY_MIN_PRICE = minPrice
? SQL` (nft.search_order_price >= ${minPrice} OR (trades.assets -> 'received' ->> 'amount')::numeric(78) >= ${minPrice})`
Expand Down
22 changes: 14 additions & 8 deletions src/ports/nfts/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,9 @@ function getRarityWhereStatement(rarities?: Rarity[]): SQLStatement | null {
}

function getFilteredNFTCTE(nftFilters: GetNFTsFilters, uncapped = false): SQLStatement {
// Define each filter condition separately
const FILTER_BY_OWNER = nftFilters.owner
? SQL` owner_id IN (SELECT id FROM squid_marketplace.account WHERE address = ${nftFilters.owner.toLocaleLowerCase()}) `
: null
const ownerEthereumAddress = nftFilters.owner ? `${nftFilters.owner.toLocaleLowerCase()}-ETHEREUM` : null
const ownerPolygonAddress = nftFilters.owner ? `${nftFilters.owner.toLocaleLowerCase()}-POLYGON` : null
const FILTER_BY_OWNER = nftFilters.owner ? SQL` owner_id = ${ownerEthereumAddress} OR owner_id = ${ownerPolygonAddress} ` : null
const FILTER_BY_CATEGORY = nftFilters.category ? SQL` category = ${nftFilters.category.toLocaleLowerCase()} ` : null
const FILTER_BY_TOKEN_ID = nftFilters.tokenId ? SQL` token_id = ${nftFilters.tokenId} ` : null
const FILTER_BY_ITEM_ID = nftFilters.itemId ? SQL` LOWER(item_id) = LOWER(${nftFilters.itemId}) ` : null
Expand Down Expand Up @@ -220,6 +219,13 @@ export function getTradesCTE(filters: GetNFTsFilters, addHavingStatement = true)
'issued_id', assets_with_values.issued_id,
'nft_name', assets_with_values.nft_name
)) as assets,
/* CASE #1: Single NFT (if you only expect ONE 'sent' per trade) */
MAX(assets_with_values.contract_address)
FILTER (WHERE assets_with_values.direction = 'sent')
AS sent_contract_address,
MAX(assets_with_values.token_id)
FILTER (WHERE assets_with_values.direction = 'sent')
AS sent_token_id,
CASE
WHEN COUNT(CASE WHEN trade_status.action = 'cancelled' THEN 1 END) > 0 THEN 'cancelled'
WHEN (
Expand Down Expand Up @@ -389,7 +395,7 @@ export function getNFTsQuery(nftFilters: GetNFTsFilters & { rentalAssetsIds?: st
LEFT JOIN squid_marketplace.ens ens ON ens.id = nft.ens_id
LEFT JOIN squid_marketplace.account account ON nft.owner_id = account.id
LEFT JOIN squid_marketplace.item item ON item.id = nft.item_id
LEFT JOIN trades ON (trades.assets -> 'sent' ->> 'token_id')::numeric = nft.token_id AND trades.assets -> 'sent' ->> 'contract_address' = nft.contract_address AND trades.status = 'open' AND trades.signer = account.address
LEFT JOIN trades ON trades.sent_contract_address = nft.contract_address AND trades.sent_token_id::numeric = nft.token_id AND trades.status = 'open' AND trades.signer = account.address
`
.append(getNFTWhereStatement(nftFilters))
.append(getMainQuerySortByStatement(nftFilters.sortBy))
Expand Down Expand Up @@ -455,9 +461,9 @@ function getNFTWhereStatement(nftFilters: GetNFTsFilters): SQLStatement {
}

function getRecentlyListedNFTsCTE(nftFilters: GetNFTsFilters): SQLStatement {
const FILTER_BY_OWNER = nftFilters.owner
? SQL` owner_id IN (SELECT id FROM squid_marketplace.account WHERE address = ${nftFilters.owner.toLocaleLowerCase()}) `
: null
const ownerEthereumAddress = nftFilters.owner ? `${nftFilters.owner.toLocaleLowerCase()}-ETHEREUM` : null
const ownerPolygonAddress = nftFilters.owner ? `${nftFilters.owner.toLocaleLowerCase()}-POLYGON` : null
const FILTER_BY_OWNER = nftFilters.owner ? SQL` owner_id = ${ownerEthereumAddress} OR owner_id = ${ownerPolygonAddress} ` : null
const FILTER_BY_CATEGORY = nftFilters.category ? SQL` category = ${nftFilters.category.toLowerCase()} ` : null
const FILTER_BY_TOKEN_ID = nftFilters.tokenId ? SQL` token_id = ${nftFilters.tokenId} ` : null
const FILTER_BY_ITEM_ID = nftFilters.itemId ? SQL` LOWER(item_id) = LOWER(${nftFilters.itemId}) ` : null
Expand Down
2 changes: 1 addition & 1 deletion src/ports/orders/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ export function getLegacyOrdersQuery(): string {
ord.expires_at,
ord.network
FROM squid_marketplace."order" ord
JOIN squid_marketplace."nft" nft ON ord.nft_id = nft.id AND nft.owner_address = ord.owner`
JOIN squid_marketplace."nft" nft ON ord.nft_id = nft.id`
}

export interface OrderQueries {
Expand Down

0 comments on commit 04343b3

Please sign in to comment.