aboutsummaryrefslogtreecommitdiffstats
path: root/benchmarks/tpcc/data.py
blob: 82ebb075a9f11b391ea7bb0cb21ba1b807528198 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
"""TPC-C's initial database (clause 4.3.3.1) for W warehouses, as rows of the
records in tpcc.aup (each composite key packed into one number, as there),
and the same rows for SQLite's tables with their own keys. Texts the
transactions only carry along are left out (see tpcc.aup). Money is in
cents and a rate in ten-thousandths, integers (i64s in tpcc.aup, INTEGER in
SQLite)."""
import random
import struct

ITEMS, CUSTOMERS, ORDERS, DELIVERED = 100000, 3000, 3000, 2100

# Each table's fields in record order (tpcc.aup), numbers but for the i64s in INTEGERS.
FIELDS = {
    'warehouses': ('id', 'tax', 'ytd'),
    'districts': ('id', 'tax', 'ytd', 'next_order', 'next_delivery'),
    'customers': ('id', 'discount', 'credit', 'balance', 'ytd_payment', 'payments', 'deliveries', 'last_order'),
    'items': ('id', 'price'),
    'stock': ('id', 'quantity', 'ytd', 'orders', 'remote'),
    'orders': ('id', 'customer', 'entry', 'carrier', 'lines', 'local'),
    'new_orders': ('id',),
    'lines': ('id', 'item', 'supply', 'delivery', 'quantity', 'amount'),
}
INTEGERS = {'tax', 'ytd', 'discount', 'balance', 'ytd_payment', 'price', 'amount'}


def district_key(w, d):
    return w * 10 + d


def customer_key(w, d, c):
    return district_key(w, d) * 3000 + c


def order_key(w, d, o):
    return district_key(w, d) * 10000000 + o


def generate(warehouses, seed=1, now=1.7e12):
    """The tables as lists of tuples in FIELDS order."""
    rng = random.Random(seed)
    tables = {name: [] for name in FIELDS}
    tables['items'] = [(i, rng.randint(100, 10000)) for i in range(1, ITEMS + 1)]
    for w in range(1, warehouses + 1):
        tables['warehouses'].append((w, rng.randint(0, 2000), 30000000))
        tables['stock'].extend((w * 100000 + i, rng.randint(10, 100), 0, 0, 0) for i in range(1, ITEMS + 1))
        for d in range(1, 11):
            tables['districts'].append((district_key(w, d), rng.randint(0, 2000), 3000000, ORDERS + 1, DELIVERED + 1))
            owners = list(range(1, CUSTOMERS + 1))
            rng.shuffle(owners)
            last = {}
            for o in range(1, ORDERS + 1):
                key, count, delivered = order_key(w, d, o), rng.randint(5, 15), o <= DELIVERED
                tables['orders'].append((key, customer_key(w, d, owners[o - 1]), now,
                                         rng.randint(1, 10) if delivered else 0, count, 1))
                last[owners[o - 1]] = key
                if not delivered:
                    tables['new_orders'].append((key,))
                for n in range(1, count + 1):
                    tables['lines'].append((key * 16 + n, rng.randint(1, ITEMS), w, now if delivered else 0, 5,
                                            0 if delivered else rng.randint(1, 999999)))
            for c in range(1, CUSTOMERS + 1):
                tables['customers'].append((customer_key(w, d, c), rng.randint(0, 5000),
                                            0 if rng.random() < 0.1 else 1, -1000, 1000, 1, 0, last[c]))
    return tables


def packed(table, rows):
    """A table's rows in a list's stored form (each number's binary64, each i64's two's complement, little-endian)."""
    row = '<' + ''.join('q' if field in INTEGERS else 'd' for field in FIELDS[table])
    return b''.join(struct.pack(row, *r) for r in rows)