# プライマリキーの非クラスタ化インデックス-`TableFullScan` 例
+ なぜここで`TableFullScan`が使われているのですか

```
tidb> SHOW CREATE TABLE universe.planets;
tidb> CREATE TABLE `planets` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  ...
  PRIMARY KEY (`id`) /*T![clustered_index] NONCLUSTERED */,
  ...

tidb> SELECT COUNT(*) FROM universe.planets
+----------+
| COUNT(*) |
+----------+
|       10 |
+----------+
1 row in set (0.01 sec)

tidb> EXPLAIN
  SELECT mass, gravity
  FROM universe.planets
  WHERE ~!@id BETWEEN 3 AND 8@!~;
+---------------------------+---------+-----------+---------------+--------------------------------------------------------+
| id                        | estRows | task      | access object | operator info                                          |
+---------------------------+---------+-----------+---------------+--------------------------------------------------------+
| Projection_4              | 6.00    | root      |               | universe.planets.mass, universe.planets.gravity        |
| └─TableReader_7           | 6.00    | root      |               | data:Selection_6                                       |
|   └─Selection_6           | 6.00    | cop[tikv] |               | ge(universe.planets.id, 3), le(universe.planets.id, 8) |
|     └─~!@TableFullScan@!~_5     | 10.00   | cop[tikv] | table:planets | keep order:false                                       |
+---------------------------+---------+-----------+---------------+--------------------------------------------------------+
```
![`smart`](NonClusteredTableWithPrimaryKey_ja_001_20231116.png)

------------------------------------------------------------------------------
なぜスライドのクエリに`FullTableScan`が使われているのですか。`TableFullScan`は必ずしも非効率的な操作ではありません。クエリが選択的でない場合は、`IndexRangeScan`の後に複数の`Point_Get`操作を行うよりも、`TableFullScan`の方が効率的です。

この場合、`planets`テーブルには10行しか含まれていません。選択範囲はその行の 60% をカバーするので、コストベースのオプティマイザーは`IndexRangeScan`よりも`TableFullScan`を優先します。つまり、`FullTableScan`はこの文脈では問題とは見なされません。コストベースオプティマイザーの詳細については、後の章で説明します。
