-
Notifications
You must be signed in to change notification settings - Fork 25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Optimise Contract Sizes #773
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -919,26 +919,38 @@ func (s *SQLStore) ContractSets(ctx context.Context) ([]string, error) { | |
} | ||
|
||
func (s *SQLStore) ContractSizes(ctx context.Context) (map[types.FileContractID]api.ContractSize, error) { | ||
rows := make([]struct { | ||
type size struct { | ||
Fcid fileContractID `json:"fcid"` | ||
Size uint64 `json:"size"` | ||
Prunable uint64 `json:"prunable"` | ||
}, 0) | ||
} | ||
|
||
if err := s.db. | ||
Raw(` | ||
SELECT fcid, MAX(c.size) as size, CASE WHEN MAX(c.size)>COUNT(cs.db_sector_id) * ? THEN MAX(c.size)-(COUNT(cs.db_sector_id) * ?) ELSE 0 END as prunable | ||
FROM contracts c | ||
LEFT JOIN contract_sectors cs ON cs.db_contract_id = c.id | ||
GROUP BY c.fcid | ||
`, rhpv2.SectorSize, rhpv2.SectorSize). | ||
Scan(&rows). | ||
Error; err != nil { | ||
var nullContracts []size | ||
var dataContracts []size | ||
if err := s.db.Transaction(func(tx *gorm.DB) error { | ||
// use WHERE NOT EXISTS to catch contracts that would otherwise have been caught by a LEFT JOIN | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it would be bit more helpful to explain what this query does rather than what alternative we had for it. Someone who looks at this in a week probably won't remember what the left join was about. so e.g. "fetch all contracts that don't have any useful sectors in them anymore" There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. haha yeah, fair enough |
||
if err := tx. | ||
Raw(` | ||
SELECT c.fcid, c.size, c.size as prunable FROM contracts c WHERE NOT EXISTS (SELECT 1 FROM contract_sectors cs WHERE cs.db_contract_id = c.id)`). | ||
Scan(&nullContracts). | ||
Error; err != nil { | ||
return err | ||
} | ||
|
||
// with those out of the way, we can use an INNER JOIN to get the rest | ||
return tx. | ||
Raw(` | ||
SELECT fcid, contract_size as size, CASE WHEN contract_size > sector_size THEN contract_size - sector_size ELSE 0 END as prunable FROM ( | ||
SELECT c.fcid, MAX(c.size) as contract_size, COUNT(cs.db_sector_id) * ? as sector_size FROM contracts c INNER JOIN contract_sectors cs ON cs.db_contract_id = c.id GROUP BY c.fcid | ||
) i`, rhpv2.SectorSize). | ||
Scan(&dataContracts). | ||
Error | ||
}); err != nil { | ||
return nil, err | ||
} | ||
|
||
sizes := make(map[types.FileContractID]api.ContractSize) | ||
for _, row := range rows { | ||
for _, row := range append(nullContracts, dataContracts...) { | ||
if types.FileContractID(row.Fcid) == (types.FileContractID{}) { | ||
return nil, errors.New("invalid file contract id") | ||
} | ||
|
@@ -962,11 +974,10 @@ func (s *SQLStore) ContractSize(ctx context.Context, id types.FileContractID) (a | |
|
||
if err := s.db. | ||
Raw(` | ||
SELECT MAX(c.size) as size, CASE WHEN MAX(c.size)>(COUNT(cs.db_sector_id) * ?) THEN MAX(c.size)-(COUNT(cs.db_sector_id) * ?) ELSE 0 END as prunable | ||
FROM contracts c | ||
LEFT JOIN contract_sectors cs ON cs.db_contract_id = c.id | ||
WHERE c.fcid = ? | ||
`, rhpv2.SectorSize, rhpv2.SectorSize, fileContractID(id)). | ||
SELECT contract_size as size, CASE WHEN contract_size > sector_size THEN contract_size - sector_size ELSE 0 END as prunable FROM ( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this new query faster? Or did you just refactor it? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's marginally faster. It avoids doing |
||
SELECT MAX(c.size) as contract_size, COUNT(cs.db_sector_id) * ? as sector_size FROM contracts c LEFT JOIN contract_sectors cs ON cs.db_contract_id = c.id WHERE c.fcid = ? | ||
) i | ||
`, rhpv2.SectorSize, fileContractID(id)). | ||
Take(&size). | ||
Error; err != nil { | ||
return api.ContractSize{}, err | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
null
requires some insider knowledge on the query we had before. I'd recommend something likeunusedContracts
andusedContracts
to indicate that it's just contracts without sectors.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I updated the comments on the query to better explain what's happening. I'd like to keep
nullContract
because for me it's the only name that really makes sense. I don't likeunusedContracts
oremptyContracts
because if they're unused or empty why would you be interested in theirsize
field for pruning...