MySQLはconnect_by_isleaf MySQLメソッドまたはストアドプロシージャに似た機能を実装します

MySQLはconnect_by_isleaf MySQLメソッドまたはストアドプロシージャに似た機能を実装します

最近、特に異常なビジネス需要があり、テーブルがあります

テーブル「デモ」を作成します(
 `id` int(11) 符号なし NOT NULL AUTO_INCREMENT,
 `tid` int(11) デフォルト '0',
 `pid` int(11) デフォルト '1',
 主キー (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3000124 デフォルトCHARSET=utf8;

以上です。レコードの行数は 300 万行を超えます。各 pid はこの ID の最上位カテゴリを記録し、tid はその親カテゴリです。
ここでの要件は、ID を指定してそのサブセット メンバーをすべて見つけ、この pid の値を新しく指定した値に変更することです。 !
PHP で実行したところ、実行に約 50 秒以上かかり、非常に苦痛でした。 ! !
すべてのサブセットを再帰的に検索し、その PID を変更する必要があり、これは非常に手間のかかる作業です。

Oracle には connect_by_isleaf というメソッドがあり、すべてのサブセットを簡単に見つけることができますが、私は MySQL を使用しています...

そこで、ここではMySQLメソッドやストアドプロシージャを使用して実装した経験について簡単に書きます。

1つ目: MySQL方式

CREATE DEFINER=`root`@`localhost` FUNCTION `lvtao_demo_a`(rootId int) 戻り値 text CHARSET utf8
  SQLデータの読み取り
  コメント「デモ」
始める

sTemp テキストを宣言します。
sTempChd テキストを宣言します。

SET sTempChd =cast(rootId を CHAR として)。
sTemp を '' に設定します。

sTempChdがnullではない場合
  SET sTemp = concat(sTemp,',',sTempChd);
  SELECT group_concat(id) INTO sTempChd FROM demo where FIND_IN_SET(tid,sTempChd)>0;
終了しながら;

sTemp を返します。

終わり;

使用方法は

lvtao_demo_a(5)を選択します。

しかし、テストしていたところ、300 万個のデータがクラッシュしてしまいました。 ! !

行 1 の列 'sTemp' のデータが長すぎます

利点: シンプル、便利、再帰呼び出しレベルの深さに制限なし (max_sp_recursion_depth、最大 255)。
デメリット: 長さが限られている。

2番目のタイプ: ストアドプロシージャ + 中間テーブル

区切り文字 ;;
CREATE DEFINER=`root`@`localhost` PROCEDURE `sss`(IN pid int, IN rootid int)
始める
   
done INT DEFAULT FALSE を宣言します。
id TEXT を宣言します。
DECLARE cur1 CURSOR FOR SELECT id FROM demo WHERE tid=pid;
NOT FOUND SET done = TRUE の継続ハンドラーを宣言します。

max_sp_recursion_depth を 200 に設定します。
 
オープンcur1;
  read_loop: ループ
    cur1 を id にフェッチします。
    完了したら
      read_loop を終了します。
    終了の場合;
    INSERT INTO temp (rootid,zid) values ​​(rootid, id);
    sss(id,rootid) を呼び出します。
  ループを終了;
cur1 を閉じます。

終わり;;
区切り文字 ;

ハハハ、300万のデータもボールの中に詰まってるよ〜〜〜

別の方法を考えよう~~~~もうこれ以上は気にしない

以下もご興味があるかもしれません:
  • Linux 上の MySQL でストアド プロシージャを使用してレコードをバッチで生成する方法
  • Mybatis 呼び出し MySQL ストアド プロシージャのシンプルな実装
  • MySQL と Oracle の違いの比較: 5: ストアド プロシージャと関数
  • mysqlストアドプロシージャは重複データを判定し、挿入しません
  • Java で MySQL ストアド プロシージャを呼び出す方法の詳細な説明
  • MySQL データベースのストアド プロシージャによるツリー トラバーサルの実装
  • MySQL ストアド プロシージャの最適化の例
  • MySQL のストアド プロシージャの分析例とストアド プロシージャの呼び出し方法
  • MySQL ストアド プロシージャ、カーソル、トランザクションの例の詳細な説明

<<:  Vue の計算プロパティとリスナーの使用の概要

>>:  Docker で ElasticSearch をデプロイする方法

推薦する

thead、tfoot、tbodyを使用して表を作成します

これらの 3 つのタグを間違った方法で使用して、タイトルを表に沿わせたり、tbody の高さを固定し...

Tomcatc3p0 で jnid データ ソースを構成する 2 つの実装方法の分析

c3p0の使用c3p0jarパッケージをインポートする <!-- https://mvnrep...

JS は Baidu 検索ボックスを実装します

この記事の例では、Baidu検索ボックスを実装するためのJSの具体的なコードを参考までに共有していま...

MySQLで論理SQLを置き換える際の落とし穴を回避する方法の詳細な説明

重複キーの置換と挿入の違い置換の使用法競合がない場合、挿入と同等となり、他の列のデフォルト値が使用さ...

Docker-compose は Docker プライベート ウェアハウスのステップを迅速に構築します

docker-compose.ymlを作成し、次の内容を入力します。 バージョン: '3&#...

Linux に MySQL 8.0.x をインストールするための完全な手順

マイグレーションMySQL 入門MySQL はもともとオープンソースのリレーショナル データベース管...

ウェブページのテーブルの境界線を設定する方法

<br />前回は、Web テーブルにセルの線を設定する方法を学びました。今日は、Web...

ウェブページを自動更新するための 3 つのコード

実際、この効果を実現するのは非常に簡単で、この効果は特殊効果と呼ぶことすらできません。次のコードを ...

MySQLで大きなテーブルを正常に削除する方法の詳細な説明

序文テーブルを削除するには、無意識に思い浮かぶコマンドは、DROP TABLE "テーブル...

Vue3 のリアクティブ関数 toRef 関数 ref 関数の紹介

目次リアクティブ機能使用法: toRef 関数 (理解するだけ)使用法: ref関数レスポンシブデー...

IEのクラッシュバグ

コードをコピーコードは次のとおりです。 <スタイル タイプ="text/css&qu...

Linux のよく使うコマンドの使い方を詳しく解説(第 2 回)———— テキストエディタのコマンド vi/vim

vi/vim の紹介どちらもマルチモード エディターです。違いは、vim が vi のアップグレー...

Tomcat でのコネクタ構成

JBoss は Tomcat を Web コンテナとして使用するため、JBoss の Web コンテ...

CSS ペイント API: CSS のような描画ボード

1. Canvas画像をCSS背景画像として使用するCSS ペイント API は、Canvas キャ...

MySQL統計テーブルのサイズを説明する例

各データベース内の各テーブルのサイズをカウントすることは、データ ガバナンスの最も単純な要件の 1 ...