 |
IDS Forum
Re: Question about sysindexes.clust
Posted By: Art Kagel Date: Tuesday, 18 November 2008, at 4:28 p.m.
In Response To: Re: Question about sysindexes.clust (Obnoxio The Clown)
OK Clown, you asked for my analysis, you got it. There are:
69million rows
rowsize ranges from 155 to 244 bytes (e to a varchar column) (8-12 rows fit
per page on 2K pages) assume an average of 10 rows per page
Estimated number of data pages: 7 million
Estimated number of index pages for table qty_det for the selected index:
410,000 with FILLFACTOR = 100
FILLFACTOR = 50: 820,000 pages of index (168 keys per page: 2020/
(4byte key + 4byte rowid + 50% internal overhead))
Those facts in mind we can analyse what may be happening during this query
before and after CLUSTERING or sorting the incoming data which accomplishes
the same thing as long as the data load is single threaded.
Searching the index for this table for the estimated 1,094,000 rows of table
qty_head which match the selection criteria (I'm assuming that the
optcombo_qty table adds little filter value since it is searched AFTER the
join between qty_head and qty_det) would require reading from a minimum of
6,500 index pages for table qty_det if ALL 1.1million matching rows had
sequential serial numbers to 820,000 pages if the serial values are evenly
distributed across the 69 million value range. Then if the rows are not
stored on the same data pages there may be as many as 1.1million data pages
to be read (minimum ~100,000 pages). That would require a cache of at least
106,500 pages just to hold the data and index keys for this one table plus
additional space for the other two tables in the query and for other queries
- and a maximum of 2.2 million pages. Since originally the data was likely
to have been fairly randomely distributed across the disks due to prior
deletions and VARCHAR row relocations, the number of pages needed in cache
will tend towards the upper limit of 2.2 million rather than the lower
limit. I assume that the cache on this server is not in excess of 2.5
million pages.
Now, if the rows are sorted into serial number order when loaded (or after
CLUSTERING), then the data rows that we are most likely to be interested in
(assuming we are interested mostly in the most recent rows added to the
table) are all contiguous on disk as are their keys in the index. That
means the number of disk pages needed to be read into cache (and the chances
that a page needed for more than one row has to be read more than once due
to timing out of the cache during the search) are minimized to only 106,500
pages as compared to the worst case - that the rows we are interested in are
scattered all over the disk due to the data not being sorted.
Add to this the possibility that since these rows contain a VARCHAR column
that may have grown over time, there may be many of these rows that required
two IOs to fetch into memory not one before any reorganization. Now the
actual timings show that the actual distribution of data on disk was far
from worst case, but also far worse that the best case.
So, back to the original question: Do we watch the
sysindices/sysindexes.cluster column to determine when a table should be
reorganized? Honestly and embarrasedly, no. Most of us have fallen away
from that particular optimization. I used to look at this in 4.0 and 5.0
days, but have not concerned with it for many years. One reason is that it
is a problem that tends to affect a small subset of queries (indeed in your
case it was killing only one particular SELECT statement) so it is one of
the last things I check for if I cannot improve a stubborn query any other
way. Also, other reorg opportunities tend to minimize the impact of this
problem as we try to minimize the number of extents in very large tables.
Art
On Tue, Nov 18, 2008 at 3:01 PM, Obnoxio The Clown
<obnoxio@serendipita.com>wrote:
> Eric Rowell wrote:
> > The following is the explain plain for the only query in the program
> which
> > isn't running correctly. The first is the plan from the normal run
> (filter
> > data had to be changed to project my job). The info after that is from a
> > diff of the explain outs for 2 more configurations. Also during all tests
> > we used a production like system (smaller CPU and slower SAN) but we know
> > the approx. modifier from prod to dev. When we sorted the data by the
> > serial_link and reloaded (changing the fragmentation as shown earlier
> things
> > run much better.
> >
> > EXPLAIN from normal run...
> >
> > QUERY:
> > ------
> > SELECT qd.option_list, oq.optid
> > FROM qty_head qh, qty_det qd, optcombo_qty oq
> > WHERE ((qh.set_no = "FINDA" AND qh.version = "09") OR
> >
> > (qh.set_no = "ORFND" AND qh.version = "01"))
> >
> > AND qh.serial_key = qd.serial_link
> >
> > AND qd.serial_key = oq.option_group_id
> >
> > AND qh.dept_code IN ("AAA","BBB","CCC","DDD","EEE")
> >
> > AND qh.community = "00"
> >
> > Estimated Cost: 1049986
> > Estimated # of Rows Returned: 1083718
> > 1) informix.qh: INDEX PATH
> >
> > (1) Index Keys: dept_code community set_no version phase_no lot
> > area_group_id
> >
> > (Key-First) (Serial, fragments: ALL)
> >
> > Lower Index Filter: (informix.qh.dept_code = 'AAA' AND
> > informix.qh.community = '00' )
> >
> > Index Key Filters: (( (informix.qh.set_no = 'FINDA' AND
> > informix.qh.version = '09')
> >
> > OR (informix.qh.set_no = 'ORFND' AND
> > informix.qh.version = '01')))
> >
> > (2) Index Keys: dept_code community set_no version phase_no lot
> > area_group_id
> >
> > (Key-First) (Serial, fragments: ALL)
> >
> > Lower Index Filter: (informix.qh.dept_code = 'BBB' AND
> > informix.qh.community = '00' )
> >
> > Index Key Filters: (( (informix.qh.set_no = 'FINDA' AND
> > informix.qh.version = '09')
> >
> > OR (informix.qh.set_no = 'ORFND' AND
> > informix.qh.version = '01')))
> >
> > (3) Index Keys: dept_code community set_no version phase_no lot
> > area_group_id
> >
> > (Key-First) (Serial, fragments: ALL)
> >
> > Lower Index Filter: (informix.qh.dept_code = 'CCC' AND
> > informix.qh.community = '00' )
> >
> > Index Key Filters: (( (informix.qh.set_no = 'FINDA' AND
> > informix.qh.version = '09')
> >
> > OR (informix.qh.set_no = 'ORFND' AND
> > informix.qh.version = '01')))
> >
> > (4) Index Keys: dept_code community set_no version phase_no lot
> > area_group_id
> >
> > (Key-First) (Serial, fragments: ALL)
> >
> > Lower Index Filter: (informix.qh.dept_code = 'DDD' AND
> > informix.qh.community = '00' )
> >
> > Index Key Filters: (( (informix.qh.set_no = 'FINDA' AND
> > informix.qh.version = '09')
> >
> > OR (informix.qh.set_no = 'ORFND' AND
> > informix.qh.version = '01')))
> >
> > (5) Index Keys: dept_code community set_no version phase_no lot
> > area_group_id
> >
> > (Key-First) (Serial, fragments: ALL)
> >
> > Lower Index Filter: (informix.qh.dept_code = 'EEE' AND
> > informix.qh.community = '00' )
> >
> > Index Key Filters: (( (informix.qh.set_no = 'FINDA' AND
> > informix.qh.version = '09' )
> >
> > OR (informix.qh.set_no = 'ORFND' AND
> > informix.qh.version = '01')))
> > 2) informix.qd: INDEX PATH
> >
> > (1) Index Keys: serial_link (Serial, fragments: ALL)
> >
> > Lower Index Filter: informix.qh.serial_key = informix.qd.serial_link
> > NESTED LOOP JOIN
> > 3) informix.optcombo_head: INDEX PATH
> >
> > (1) Index Keys: serial_key option_list option_count (Serial,
> > fragments: ALL)
> >
> > Lower Index Filter: informix.qd.optcombo_head_key =
> > informix.optcombo_head.serial_key
> > NESTED LOOP JOIN
> > 4) product.qty_detail: INDEX PATH
> >
> > (1) Index Keys: serial_key (Serial, fragments: ALL)
> >
> > Lower Index Filter: informix.qd.serial_key =
> > product.qty_detail.serial_key
> > NESTED LOOP JOIN
> > 5) informix.oq: INDEX PATH
> >
> > (1) Index Keys: optcombo_head_key opt_id (Key-Only) (Serial,
> > fragments: ALL)
> >
> > Lower Index Filter: informix.oq.optcombo_head_key =
> > product.qty_detail.optcombo_head_key
> > NESTED LOOP JOIN
> >
> > Diff of Explain Plan after just reloading the table:
> > < Estimated Cost: 1049986
> > < Estimated # of Rows Returned: 1083718
> > ---
> >> Estimated Cost: 2348476
> >> Estimated # of Rows Returned: 1486409
> >
> > Diff of Explain Plan after reloading the sorting data (using
> serial_link):
> > < Estimated Cost: 1049986
> > < Estimated # of Rows Returned: 1083718
> > ---
> >> Estimated Cost: 851019
> >> Estimated # of Rows Returned: 1094319
> >
> > The cost difference appears to be in line with the change to the
> > sysindex.clust value for the indexes.
>
> And which table do you query from to see if there are missing rows and
> insert them?
>
> Basically, I can't disagree with your analysis, I'm just curious as to
> why ordering should have such a measurable impact on performance given
> the explain plan. In general, it doesn't.
>
> I feel like there is something lurking in the nether hells of my brain,
> but I can't quite drag it out. Last time I saw something like this, the
> root cause was "XXXX in my opinion" but I can't remember what "XXXX" was.
>
> Give me time. Or Art will be along shortly. :o)
>
> --
> Cheers,
> Obnoxio The Clown
>
> http://obotheclown.blogspot.com
>
>
>
> *******************************************************************************
> Forum Note: Use "Reply" to post a response in the discussion forum.
>
>
--
Art S. Kagel
Oninit (www.oninit.com)
IIUG Board of Directors (art@iiug.org)
Disclaimer: Please keep in mind that my own opinions are my own opinions and
do not reflect on my employer, Oninit, the IIUG, nor any other organization
with which I am associated either explicitly or implicitly. Neither do
those opinions reflect those of other individuals affiliated with any entity
with which I am affiliated nor those of the entities themselves.
Messages In This Thread
IDS Forum is maintained by Administrator with WebBBS 5.12.
|
 |