-
Olav Sandstaa authored
The assert was hit when calling Unique::get_use_cost() to calculate the cost of using Unique to process 0 keys. Unique::get_use_cost() uses an implementation of Stirling's approximation to calculate the number of compare operations this would take. The correct number of compare operations for comparing 0 keys should be 0 but due to using Stirling's approximation, the estimate became -0.12. This caused the assert in Cost_model_table::key_compare_cost() to hit. In this case, Unique is used by the index merge code to calculate the cost of index merge of two indexes. The index merge code gets the rows estimates from the storage engine by calling handler::records_in_range(). Most storage engines will never return 0 as the rows estimate even when the table is empty since there is an assumption that the optimizer could interpret this as the range scan would return 0 rows (ie. interpret it as an exact number, not an estimate). The new native partition engine in InnoDB can in some cases return 0 as the result from handler::records_in_range(). This is the cause for the index merge code to call Unique::get_use_cost() with 0 in the key argument. The fix for this is to make Unique::get_use_cost() handle that it is called with 0 as the number of keys argument by adding a special case to the implementation of Stirling's approximation so that it does not return a negative number.
Olav Sandstaa authoredThe assert was hit when calling Unique::get_use_cost() to calculate the cost of using Unique to process 0 keys. Unique::get_use_cost() uses an implementation of Stirling's approximation to calculate the number of compare operations this would take. The correct number of compare operations for comparing 0 keys should be 0 but due to using Stirling's approximation, the estimate became -0.12. This caused the assert in Cost_model_table::key_compare_cost() to hit. In this case, Unique is used by the index merge code to calculate the cost of index merge of two indexes. The index merge code gets the rows estimates from the storage engine by calling handler::records_in_range(). Most storage engines will never return 0 as the rows estimate even when the table is empty since there is an assumption that the optimizer could interpret this as the range scan would return 0 rows (ie. interpret it as an exact number, not an estimate). The new native partition engine in InnoDB can in some cases return 0 as the result from handler::records_in_range(). This is the cause for the index merge code to call Unique::get_use_cost() with 0 in the key argument. The fix for this is to make Unique::get_use_cost() handle that it is called with 0 as the number of keys argument by adding a special case to the implementation of Stirling's approximation so that it does not return a negative number.
Loading