Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Physically, each ETS node will introduce a thread. Thus, the intersection operator must synchronize the upstream input threads in order to generate the correct result. In order to have a pipeline operateoperation, the intersection is implemented as in a sort-merge manner. Therefore, each input is required to be sorted. The synchronization is handled by the thread of input zeroNo.0, which means the thread 0 will call the writer.open/nextFrame/close functions. If we authorize arbitrary threads to do such taskpush forward, the downstream operator will be confused to synchronize on , especially in synchronizing their locks. The core logical intersection function is as below:

  1. do 
    1. find the max input: max
    2. for each input i
      1. keep popping until it matches max. then match++;
      2. if > max, break
    3. If match == inputArity
      1. output max
  2. while all inputs haven't been no input is closed.

If any of the input is fully consumed, the operator is closed.

...

Each test will run three times:

  • 1st. with BTree index on TweetUser.create_at only, 
  • 2nd. with BTree index on UserTweet.create_at onlyat only
  • 3rd. with both indexes presents, consequently, the intersection is introduced.

...

   ScanUserCreateAtIndexTweetCreateAt IndexIntersectionReductionSpeedUp
resultmonthminutesTime (Avg last 5)    
43101--0200-0992914213252602.61%54
92801--0200-1992914322656602.84%55
145801--0200-2993414432873491.31%97
199701--0200-3993214342780441.06%79
250401--0200-4993014252892351.21%54
298901--0200-59933141631109221.70%29

Table 2. Fix the Tweet.create_at $min_start = 00, $min_end = 09, increasing the User.create_at selectivity

   ScanUserCreateAtIndexTweetCreateAt IndexIntersectionReduction
resultmonthminutesTime (Avg last 5)    
43101--0200-0992914213252602.61%54
67001--0300-0993218912948622.79%69
92901--0400-0992824012461502.81%03
114001--0500-0993129112869461.09%86
147101--0600-0993336712665481.41%94
185901--0700-0993244912584321.80%49
216601--0800-0993152512687301.95%45
243801--0900-0993258012794251.98%35
268201--1000-09939648127104181.11%22
301101--1100-09934710125110121.00%14
334601--1200-0993378112712051.51%06

Table 3. Both Tweet.create_at and User.create_at increasing the selectivity

   ScanUserCreateAtIndexTweetCreateAt IndexIntersectionReduction
resultmonthminutesTime (Avg last 5)    
43101--0200-0992914213252602.61%54
142901--0300-1993319022867642.74%84
194501--0400-1993323922667703.35%37
368601--0500-2993429432283713.77%54
481601--0600-29936370324102683.52%18
832001--0700-39931453425123713.06%46
1220201--0800-49932522529146723.03%58
1379101--0900-49934582527157703.21%36
1848901--1000-59937644630191693.68%30

We can see that intersection is the best one choice under current above settings. The total time reduction is from 5% to 70%speed up to the fast single index path is up to 3.5 times. If the selectivities of two indexes are vary indexes vary a lot in the selectivity, then the benefit of intersection may not that much. If the two indexes are of the similar selectivity the intersection can achieve 60% ~ 70% total time reductiontwo to three times faster.

On disk case

The test dataset is changing to the 8.2G dataset. In order to flush the cache, we load the same dataset to another ds_copy dataset. Every time when we run the selection, we scan this 8.2G ds_copy once to invalidate the cache pages. Due to the slowness of the on disk case, we warm up the query only once and record the average time of the next three times.

...

Though the two access methods have very different execution time, the intersection tends to catch with the fastest one. The overhead of intersection compares to the fastest path is from 15% to 78%. While , its speedup compares to the slowest one is about 5~10 times faster. 

Why the Tweet.creat_at access path is so fast?  

The answer is that the order of primary key (Tweet.id) is consistent with the order of Tweet.create_at. We speculates speculate that the Tweet.id was generated by the Tweet.create_at. Thus, this secondary index is actually clustered as the primary index. As the consequence, the IO time to fetch each record is clustered. The general performance of the secondary index lookup should be as slow as the User.create_at access path.

...

Because we only have one disk. First, the Tweet.create_at path has to wait for the User.create_at to finish a frame to operate the intersection. These two index search is battling the disk read. Second, although the intersection itself can be finished as long as one of the input is done, we can not stop the other index scan based on our push model. Hence, the primary search is also competing competing on the disk resource with the two index searches. 

General secondary index comparison

We know the As shown in the previous result, the index on Tweet.create_at is a primary-like key. Then we replace that access path with an RTree path which is build clustered secondary index, which is a special case for the secondary index. To test a more general case, we create an RTree on the Tweet.place.bounding_box..boudingbox which is a rectangle area. We create a circle area around LA county. By increasing the radius, we can increase the selectivity of that RTree. The query is as below

Code Block
use dataverse twitter; 
let $ms_start := date("2010-$month_start-01") 
let $ms_end := date("2010-$month_end-28") 
let $region := create-circle(create-point(-118.125,33.939), $radius)
let $result := for $t in dataset ds_tweets 
               where $t.user.create_at >= $ms_start and $t.user.create_at < $ms_end 
               and spatial-intersect($t.place.bounding_box, $region)
               and $t.place = "Unite State" return $t return count($result)
               return $t
return count($result)

Table 6. Fix User.create_at condition for one month and increase the $radius range. 

   Scanuser time IndexRtree Indexintersectionspeedup
resultmonthhourTime (Avg last 5)    
139001--020.01  106159929311.4235446
155101--020.02  10712710012 
157501--020.03  10814310278 
617101--020.04  11126431850 
619301--020.05  11291632001 
668901--020.06  11167333952 
690001--020.07  11101234946 
690001--020.08  11157034937 

The experiment is slow. Stay tuned. 

...