Interpretation of the delete process of Yunxi database

The execution process of the delete statement delete from table where xxx in Yunxi database is:

 

delete is mainly divided into two parts, one part is the scan process, which pulls the data in the table, and the second part, according to the filter conditions, calls the b.Del() function to delete the corresponding data. The relevant logical plan object diagram is:

 

The deleteNode contains a scanNode, which is responsible for pulling the data in the table. deleteRun includes the information of the actual delete operation, including the index information of the data in the table, transaction related information txn, batch..., and tabledesc and other information.

Among them, when constructing the logical plan, there is a maybeCreateDeleteFastNode function to judge whether the deleterange operation can be executed. The judgment conditions are:

1. Whether there is an index in the table, if so, deleterange cannot be executed

2. Whether the table is a staggered table, if so, deleterange cannot be executed

3. Whether the primary key of the table is associated with the foreign key of other tables, if so, deleterange cannot be executed

4. Whether the renderNode is scanNode, if not, deleterange cannot be executed

5. The filter condition is not pushed down to span, and deleterange cannot be executed

6. When there is a limit keyword, deleterange cannot be executed

After the above filter conditions are met, if deleteRange can be executed, the deleteNode in it will be converted into deleteRangeNode. During execution, the startExec of rowCountNode will directly call the startExec of deleteRangeNode, and the data will be deleted by directly issuing the DelRange operation on the span. Will not call into BatchNext.

Part of the deleteRange process code:

spans := make([]roachpb.Span, len(d.spans))
    copy(spans, d.spans)
    for len(spans) != 0 {
        b := params.p.txn.NewBatch()
        for _, span := range spans {
            if traceKV {
                log.VEventf(ctx, 2, "DelRange %s - %s", span.Key, span.EndKey)
            }
            b.DelRange(span.Key, span.EndKey, true /* returnKeys */)
        }
        b.Header.MaxSpanRequestKeys = TableTruncateChunkSize
 
        if err := params.p.txn.Run(ctx, b); err != nil {
            return err
        }
 
        spans = spans[:0]
        for _, r := range b.Results {
            var prev []byte
            for _, keyBytes := range r.Keys {
                // If prefix is same, don't bother decoding key.
                if len(prev) > 0 && bytes.HasPrefix(keyBytes, prev) {
                    continue
                }
 
                after, ok, err := d.fetcher.ReadIndexKey(keyBytes)
                if err != nil {
                    return err
                }
                if !ok {
                    return pgerror.NewAssertionErrorf("key did not match descriptor")
                }
                k := keyBytes[:len(keyBytes)-len(after)]
                if !bytes.Equal(k, prev) {
                    prev = k
                    d.rowCount++
                }
            }
            if r.ResumeSpan != nil && r.ResumeSpan.Valid() {
                spans = append(spans, *r.ResumeSpan)
            }
        }
    }

 

{{o.name}}
{{m.name}}

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=324103564&siteId=291194637