Optimizing Database Index Design and Calculating Dice Sum Probabilities with Dynamic Programming

Understanding InnoDB's indexing mechanism clarifies why lengthy fields are suboptimal as primary keys. Since secondary indexes reference the primary index, an oversized primary key inflates secondary indexes. Similar, using non-monotonic feilds as primary keys in InnoDB is inefficient because the data file is structured as a B+Tree. Non-monotonic inserts force frequent tree splits to maintain balance, degrading performance. Auto-incrementing fields offer a superior alternative for primary keys.

For computing probabilities of sums from rolling n dice, a naive recursive approach often leads to timeouts due to exponential complexity. Consider this initial implementation:

func computeDiceProbabilities(n int) []float64 {
    freqMap := make(map[int]int)
    totalOutcomes := int(math.Pow(6, float64(n)))
    var dfs func(remaining int, currentSum int)
    dfs = func(remaining int, currentSum int) {
        if remaining == 0 {
            freqMap[currentSum]++
            return
        }
        for face := 1; face <= 6; face++ {
            dfs(remaining-1, currentSum+face)
        }
    }
    dfs(n, 0)
    probabilities := make([]float64, 0)
    for sum := n; sum <= 6*n; sum++ {
        prob := float64(freqMap[sum]) / float64(totalOutcomes)
        probabilities = append(probabilities, prob)
    }
    return probabilities
}

This method models the problem as a tree with six branches per node, but it redundantly processes overlapping subproblems. To optimize, store intermediate results using a bottom-up dynamic programming approach. Here's an improved version:

func computeDiceProbabilitiesDP(n int) []float64 {
    dp := make([][]int, n+1)
    for i := range dp {
        dp[i] = make([]int, 6*n+1)
    }
    for face := 1; face <= 6; face++ {
        dp[1][face] = 1
    }
    for diceCount := 2; diceCount <= n; diceCount++ {
        for currentSum := diceCount; currentSum <= 6*diceCount; currentSum++ {
            for face := 1; face <= 6 && face <= currentSum; face++ {
                dp[diceCount][currentSum] += dp[diceCount-1][currentSum-face]
            }
        }
    }
    totalOutcomes := math.Pow(6, float64(n))
    probabilities := make([]float64, 5*n+1)
    for idx, sum := range dp[n][n : 6*n+1] {
        probabilities[idx] = float64(sum) / totalOutcomes
    }
    return probabilities
}

This dynamic programming solution efficiently calcualtes frequencies by iteratively building up results for increasing dice counts, avoiding recomputation and ensuring linear time complexity relative to the number of dice.

Tags: InnoDB indexing Dynamic Programming Probability Go

Posted on Thu, 07 May 2026 18:23:42 +0000 by daucoin