package com.taobao.tddl.optimizer.costbased;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import com.taobao.tddl.common.model.ExtraCmd;
import com.taobao.tddl.optimizer.BaseOptimizerTest;
import com.taobao.tddl.optimizer.config.table.IndexMeta;
import com.taobao.tddl.optimizer.core.ast.QueryTreeNode;
import com.taobao.tddl.optimizer.core.ast.query.TableNode;
import com.taobao.tddl.optimizer.core.expression.IFilter;
import com.taobao.tddl.optimizer.core.expression.ISelectable;
import com.taobao.tddl.optimizer.costbased.chooser.IndexChooser;
import com.taobao.tddl.optimizer.exceptions.QueryException;
import com.taobao.tddl.optimizer.utils.FilterUtils;
/**
* @author Dreamond
*/
public class IndexChooserTest extends BaseOptimizerTest {
private Map extraCmd = new HashMap();
private List<ISelectable> emptyColumns = new ArrayList<ISelectable>();
@Before
public void setUp() {
extraCmd.put(ExtraCmd.CHOOSE_INDEX, true);
}
@Test
public void testChooseIndex() throws QueryException {
TableNode table = new TableNode("TABLE1");
QueryTreeNode qn = table.query("ID=1");
qn.build();
IndexMeta index = IndexChooser.findBestIndex(table.getTableMeta(),
emptyColumns,
toDNFFilter(table.getWhereFilter()),
table.getTableName(),
extraCmd);
Assert.assertNotNull(index);
Assert.assertEquals(index.getName(), "TABLE1");
}
/**
* NAME=1的选择性显然比SCHOOL>1好,所以选择二级索引NAME
*
* @throws QueryException
*/
@Test
public void testChooseIndex列出现的顺序不影响索引选择() throws QueryException {
TableNode table1 = new TableNode("TABLE1");
QueryTreeNode qn1 = table1.query("SCHOOL>1&&NAME=1");
qn1.build();
IndexMeta index = IndexChooser.findBestIndex(table1.getTableMeta(),
table1.getColumnsRefered(),
toDNFFilter(table1.getWhereFilter()),
table1.getTableName(),
extraCmd);
Assert.assertNotNull(index);
Assert.assertEquals(index.getName(), "TABLE1._NAME");
TableNode table2 = new TableNode("TABLE1");
QueryTreeNode qn2 = table2.query("NAME=1&&SCHOOL>1");
qn2.build();
index = IndexChooser.findBestIndex(table2.getTableMeta(),
table2.getColumnsRefered(),
toDNFFilter(table2.getWhereFilter()),
table2.getTableName(),
extraCmd);
Assert.assertNotNull(index);
Assert.assertEquals(index.getName(), "TABLE1._NAME");
}
/**
* 虽然C1,C2上存在组合索引,但是由于范围查询的选择度不如等值查询 因此还是选择了单索引NAME=1
*/
@Test
public void testChooseIndex单索引选择度好于组合索引() throws QueryException {
TableNode table = new TableNode("TABLE9");
QueryTreeNode qn = table.query("C1>10&&C2>3&&NAME=1");
qn.build();
IndexMeta index = IndexChooser.findBestIndex(table.getTableMeta(),
table.getColumnsRefered(),
toDNFFilter(table.getWhereFilter()),
table.getTableName(),
extraCmd);
Assert.assertNotNull(index);
Assert.assertEquals(index.getName(), "TABLE9._NAME");
}
/**
* 虽然C1,C2上都存在单索引,但是C1,C2还是组合索引,这种情况下优先选择组合索引
*
* @throws QueryException
*/
@Test
public void testChooseIndex选择组合索引() throws QueryException {
TableNode table = new TableNode("TABLE9");
QueryTreeNode qn = table.query("C1>10&&C2=3");
qn.build();
IndexMeta index = IndexChooser.findBestIndex(table.getTableMeta(),
table.getColumnsRefered(),
toDNFFilter(table.getWhereFilter()),
table.getTableName(),
extraCmd);
Assert.assertNotNull(index);
Assert.assertEquals(index.getName(), "TABLE9._C1_C2");
}
/**
* C4,C5上只存在倒排索引,单C4的选择更高,选择C4倒排
*/
@Test
public void testChooseIndex选择倒排索引() throws QueryException {
TableNode table = new TableNode("TABLE9");
QueryTreeNode qn = table.query("C4=10&&C5>3");
qn.build();
IndexMeta index = IndexChooser.findBestIndex(table.getTableMeta(),
table.getColumnsRefered(),
toDNFFilter(table.getWhereFilter()),
table.getTableName(),
extraCmd);
Assert.assertNotNull(index);
Assert.assertEquals(index.getName(), "TABLE9._C4");
}
/**
* C6,C7同时存在组合索引和倒排索引 同时有倒排和组合索引,并且选择度一样,优先选择组合
*/
@Test
public void testChooseIndex选择度相同优先选组合() throws QueryException {
TableNode table = new TableNode("TABLE9");
QueryTreeNode qn = table.query("C6=10&&C7=3");
qn.build();
IndexMeta index = IndexChooser.findBestIndex(table.getTableMeta(),
table.getColumnsRefered(),
toDNFFilter(table.getWhereFilter()),
table.getTableName(),
extraCmd);
Assert.assertNotNull(index);
Assert.assertEquals(index.getName(), "TABLE9._C6_C7");
}
@Test
public void testChooseIndex手动指定索引() throws QueryException {
TableNode table = new TableNode("TABLE9");
table.build();
table.useIndex(table.getTableMeta().getIndexs().get(0));
table.build();
System.out.println(table.toDataNodeExecutor());
}
private List<IFilter> toDNFFilter(IFilter where) {
return FilterUtils.toDNFNodesArray(where).get(0);
}
}