~launchpad-pqm/launchpad/devel

« back to all changes in this revision

Viewing changes to lib/lp/app/doc/batch-navigation.txt

  • Committer: Launchpad Patch Queue Manager
  • Date: 2011-08-09 10:30:43 UTC
  • mfrom: (13607.3.4 bug-820796)
  • Revision ID: launchpad@pqm.canonical.com-20110809103043-865kaypngiquws1f
[r=henninge][bug=820796] Make publisher scripts use the same lock
        file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
47
47
  ...     'Cupid', 'Donner', 'Blitzen', 'Rudolph']
48
48
 
49
49
 
50
 
Performance with SQLObject
51
 
==========================
52
 
 
53
 
This section demonstrates that batching generates sensible SQL queries when
54
 
used with SQLObject, i.e. that it puts appropriate LIMIT clauses on queries.
55
 
 
56
 
Imports and initialization:
57
 
 
58
 
  >>> from lp.testing.pgsql import CursorWrapper
59
 
  >>> from canonical.launchpad.database.emailaddress import EmailAddress
60
 
  >>> from canonical.launchpad.interfaces.lpstorm import IStore
61
 
  >>> ignore = IStore(EmailAddress) # Prime the database connection.
62
 
  ... # (Priming is important if this test is run in isolation).
63
 
  >>> CursorWrapper.record_sql = True
64
 
 
65
 
Prepare a query, and create a batch of the results:
66
 
 
67
 
  >>> select_results = EmailAddress.select(orderBy='id')
68
 
  >>> batch_nav = BatchNavigator(select_results, build_request(), size=10)
69
 
  >>> email_batch = batch_nav.currentBatch()
70
 
  >>> batch_items = list(email_batch)
71
 
 
72
 
Because we're only looking at the first batch, the database is only
73
 
asked for the first 11 rows. (lazr.batchnavigator asks for 11 instead
74
 
of 10 so that it can reliably detect the end of the dataset).
75
 
 
76
 
  >>> len(CursorWrapper.last_executed_sql)
77
 
  1
78
 
  >>> print CursorWrapper.last_executed_sql[0]
79
 
  SELECT ... FROM EmailAddress ... LIMIT 11...
80
 
 
81
 
Get the next 10.  The database is only asked for the next 11 rows:
82
 
 
83
 
  >>> CursorWrapper.last_executed_sql = []
84
 
  >>> email_batch2 = email_batch.nextBatch()
85
 
  >>> batch_items = list(email_batch2)
86
 
  >>> len(CursorWrapper.last_executed_sql)
87
 
  1
88
 
  >>> CursorWrapper.last_executed_sql[0].endswith('LIMIT 11 OFFSET 10')
89
 
  True
90
 
 
91
 
As seen above, simply accessing the batch doesn't trigger a SQL query
92
 
asking for the length of the entire resultset. But explicitly asking
93
 
for the length will trigger a SQL query in most circumstances.
94
 
 
95
 
  >>> CursorWrapper.last_executed_sql = []
96
 
  >>> ignored = email_batch.total()
97
 
  >>> print CursorWrapper.last_executed_sql[0]
98
 
  SELECT COUNT(*) FROM EmailAddress
99
 
 
100
 
There are exceptions. When the current batch is the last one in the
101
 
list, it's possible to get the length of the entire resultset without
102
 
triggering a COUNT query.
103
 
 
104
 
  >>> CursorWrapper.last_executed_sql = []
105
 
  >>> batch_nav = BatchNavigator(select_results, build_request(), size=50)
106
 
  >>> final_batch = batch_nav.currentBatch().nextBatch()
107
 
  >>> batch_items = list(final_batch)
108
 
  >>> ignored = final_batch.total()
109
 
  >>> print "\n".join(CursorWrapper.last_executed_sql)
110
 
  SELECT ... FROM EmailAddress ... OFFSET 0
111
 
  SELECT ... FROM EmailAddress ... OFFSET 50
112
 
 
113
 
When the current batch contains the entire resultset, it's possible to
114
 
get the length of the resultset without triggering a COUNT query.
115
 
 
116
 
  >>> CursorWrapper.last_executed_sql = []
117
 
  >>> one_page_nav = BatchNavigator(select_results, build_request(), size=200)
118
 
  >>> only_batch = one_page_nav.currentBatch()
119
 
  >>> batch_items = list(only_batch)
120
 
  >>> ignored = only_batch.total()
121
 
  >>> print "\n".join(CursorWrapper.last_executed_sql)
122
 
  SELECT ... FROM EmailAddress ... OFFSET 0
123
 
 
124
50
Multiple pages
125
51
==============
126
52
 
127
53
The batch navigator tells us whether multiple pages will be used.
128
54
 
 
55
    >>> from canonical.launchpad.database.emailaddress import EmailAddress
 
56
    >>> select_results = EmailAddress.select(orderBy='id')
 
57
    >>> batch_nav = BatchNavigator(select_results, build_request(), size=50)
129
58
    >>> batch_nav.has_multiple_pages
130
59
    True
131
60
 
 
61
    >>> one_page_nav = BatchNavigator(select_results, build_request(), size=200)
132
62
    >>> one_page_nav.has_multiple_pages
133
63
    False
134
64