ID がわかっている特定のノードから上に向かって、階層構造のノードを更新する必要があるアプリケーションがあります。これを行うには、次の MySQL ステートメントを使用します。
update node as A
join node as B
on A.lft<=B.lft and A.rgt>=B.rgt
set A.count=A.count+1 where B.id=?
テーブルには、id に主キーがあり、lft と rgt にインデックスがあります。ステートメントは機能しますが、パフォーマンスに問題があることがわかりました。対応する select ステートメントの EXPLAIN 結果を見ると、「B」テーブルについて検査された行数が非常に多いことがわかりました (おそらくテーブル全体)。
クエリを 2 つの別々のクエリに簡単に引き離すことができます。
select lft, rgt from node where id=?
LFT=result.lft
RGT=result.rgt
update node set count=count+1 where lft<=LFT and rgt>=RGT
しかし、元のステートメントが期待どおりに機能しないのはなぜですか。
リクエストに応じて、create table の省略版を以下に示します。
CREATE TABLE `node` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(255) NOT NULL,
`lft` decimal(64,0) NOT NULL,
`rgt` decimal(64,0) NOT NULL,
`count` int(11) NOT NULL default '0',
PRIMARY KEY (`id`),
KEY `name` (`name`),
KEY `location` (`location`(255)),
KEY `lft` (`lft`),
KEY `rgt` (`rgt`),
) ENGINE=InnoDB
複合インデックスを追加しようとはしていません (実際、その場で追加するために必要なアクセス レベルがありません)。しかし、データベース エンジンが二重の不等式を解決しようとする方法を考えてみると、それがどのように役立つかわかりません。