10

a VARCHAR(255), b INTInnoDBテーブルの列にインデックスがあります。2つa,bのペアがある場合、MySQLインデックスを使用して、ペアがacプログラムから同じであるかどうかを判断できますか(つまりstrcmp、数値比較を使用せずに)?

  1. MySQL InnoDBインデックスはファイルシステムのどこに保存されていますか?
  2. 別のプログラムから読み取って使用できますか?フォーマットは何ですか?
  3. インデックスを使用して、2つのキーが同じであるかどうかを判断するにはどうすればよいですか?

注:この質問への回答は、a)このタスクを実行するためにMySQLインデックスにアクセスする方法を提供するか、b)この方法でMySQLインデックスに実際にアクセス/使用できない理由を説明する必要があります。プラットフォーム固有の答えは問題ありません。私はRedHat5.8を使用しています。


以下は、この質問の以前のバージョンです。これは、より多くのコンテキストを提供しますが、実際の質問から注意をそらすようです。MySQL内でこの例を実行する方法は他にもあることを理解しており、2つ提供します。これは最適化に関する質問ではなく、動的に生成される多くの異なるクエリに存在する複雑さの一部を除外することです。

サブグループ化されたサブセレクトを使用してクエリを実行できます。

SELECT c, AVG(max_val)
FROM (
    SELECT c, MAX(val) AS max_val
    FROM table
    GROUP BY a, b) AS t
GROUP BY c

しかし、私は単一の選択でそれを行うことができるUDFを作成しました。

SELECT b, MY_UDF(a, b, val)
FROM table
GROUP by c

ここで重要なのは、フィールドaとUDFを渡し、各グループのサブグループbを手動で管理することです。a,bColumnaはvarcharであるため、これにはstrncmp一致をチェックするための呼び出しが含まれますが、かなり高速です。

しかし、私はインデックスを持っていますmy_key (a ASC, b ASC)。aとbの一致を手動でチェックする代わりに、MySQLインデックスにアクセスして使用できますか?つまりa,b、c(UDF内)の特定の行またはペアのmy_keyのインデックス値を取得できますか?もしそうなら、インデックス値はどの値に対しても一意であることが保証されますa,bか?

呼び出して、UDFからcMY_UDF(a, b, val)のmysqlインデックス値を検索したいと思います。(a,b)

4

4 に答える 4

6

元のクエリを振り返ってください

SELECT c, AVG(max_val)
FROM
(
    SELECT c, MAX(val) AS max_val
    FROM table
    GROUP BY a, b
) AS t
GROUP BY c;

まず、サブセレクトを実行して、必要なものが得られることを確認する必要があります

SELECT c, MAX(val) AS max_val
FROM table
GROUP BY a, b;

副選択の結果が正しい場合は、完全なクエリを実行します。その結果が正しければ、次のことを行う必要があります。

ALTER TABLE `table` ADD INDEX abc_ndx (a,b,c,val);

これにより、必要なすべてのデータがインデックスからのみ取得されるため、クエリが高速化されます。ソース表を参照する必要はありません。

UDF を記述することは、それを単一の SELECT と呼ぶことは、副選択をマスカレードし、クエリが必要とする以上のオーバーヘッドを作成することです。完全なクエリ (データに対する 1 つのネストされたパス) をストアド プロシージャに配置するだけで、UDF 内のほとんどのデータを取得し、単一の行の選択を繰り返し実行するよりも効果的です (O(n log n) のような実行時間で、より長い可能性があります)。Sending data州)。

更新 2012-11-27 13:46 EDT

2 つのことを行うことで、テーブルに触れずにインデックスにアクセスできます。

  • 適切なカバリング インデックスを作成する

    ALTER TABLE tableADD INDEX abc_ndx (a,b,c,val);

  • SELECT前述のクエリを実行します

クエリのすべての列がすべてインデックスにあるため、クエリ オプティマイザーはインデックスのみにアクセスします (またはインデックス ページを事前にキャッシュします)。テーブルが MyISAM の場合、次のことができます...

  1. MyISAM テーブルをセットアップして、mysqld の起動時にプリロードできる専用のキー キャッシュを設定します。
  2. を実行SELECT a,b,c,val FROM table;してインデックスページを MyISAM のデフォルトのキーキャッシュにロードします

信じてください、あなたは本当に mysqld の意思に反してインデックス ページにアクセスしたくありません。それはどういう意味ですか?

MyISAM の場合、MyISAM テーブルのインデックス ページは.MYIテーブルのファイルに格納されます。各 DML ステートメントは、完全なテーブル ロックを呼び出します。

InnoDB の場合、インデックス ページは InnoDB バッファ プールにロードされます。その結果、関連するデータ ページも InnoDB バッファー プールに読み込まれます。

Python、Perl、PHP、C++、または Java を使用してインデックス ページへのアクセスを回避する必要はありません。これは、MyISAM によって必要とされる一定の I/O またはInnoDB によって実行される一定のMVCCプロトコルのためです。

mysqld の通常のアクセス パターンを完全にバイパスできる MySQL テーブルへの低レベル アクセスを許可する NoSQL パラダイム (HandlerSocket と呼ばれる) があります。書き込みを発行するために使用するときにバグがあったため、お勧めしません。

更新 2012-11-30 12:11 EDT

前回のコメントより

私は InnoDB を使用していますが、MVCC モデルがどのように複雑になっているのかがわかります。ただし、どうやら InnoDB は 1 つのバージョン (最新) のみをインデックスに格納します。関連するテーブルへのアクセス パターンは 1 回だけ書き込み、何度も読み取りを行うため、インデックスにアクセスできれば、キーごとに 1 つの信頼できるデータを提供できます。

InnoDB に関して言えば、MVCC は何も複雑にしません。それは実際にあなたの親友になることができます:

  • 自動コミットが有効になっている場合(デフォルトで有効になっているはずです)
  • 関連するテーブルのアクセス パターンは、1 回だけ書き込み、複数回読み取ります。

アクセスされたインデックス ページが、繰り返し読み取られる場合、InnoDB バッファ プールに事実上永久に存在すると予想されます。innodb_buffer_pool_sizeが、必要な InnoDB データを保持するのに十分な大きさに設定されていることを確認します

于 2012-11-19T20:43:30.303 に答える
4

おそらく、キーに直接アクセスすることはできません。これが実際にパフォーマンス面で違いを生むとは思いません。

カバーするインデックスを正しい順序で設定すると、MySQL はハードディスクから 1 ページをフェッチせず、結果をインデックスから直接配信します。これより速いものはありません。

結果がtmp_table_sizeまたはmax_heap_table_sizeよりも大きくなっている場合、副選択がディスク上の一時テーブルになる可能性があることに注意してください。

Created_tmp_tables_disk_tables不明な場合はステータスを確認してください。

MySQL が内部一時テーブルを使用する方法の詳細については、http://dev.mysql.com/doc/refman/5.5/en/internal-temporary-tables.html を参照してください

必要に応じて、レビューのためにテーブル構造を投稿してください。

于 2012-11-14T22:16:58.183 に答える
4

MySQL の外部のインデックスにアクセスしたいだけの場合は、 MySQL ストレージ エンジンのいずれかの API を使用する必要があります。デフォルトのエンジンは InnoDB です。ここで概要を参照してください: InnoDB Internals。これは、ディスク上のデータ レイアウトとそれにアクセスするための API の両方を (非常に高いレベルで) 説明しています。より詳細な説明はここにあります: Embedded InnoDB

ただし、InnoDB API を直接使用する独自のプログラムを作成する (これは大変な作業です) のではなく、既にその作業を行っているプロジェクトの 1 つを使用できます。

  • HandlerSocket : InnoDB テーブルへの NoSQL アクセスを提供し、UDF で実行します。開発者からの非常に有益なブログ投稿を参照してください。HandlerSocket の目的は、ネットワーク デーモンとして公開される NoSQL インターフェースを提供することですが、同じ手法 (および同じコードの多く) を使用して、MySQL のクエリで使用されるものを提供することができます。

  • memcached InnoDB プラグイン. InnoDB テーブルへの memcached スタイルのアクセスを提供します。

  • HailDB : InnoDB テーブルへの NoSQL アクセスを提供し、組み込み InnoDB 上で実行します。会議のプレゼンテーションを参照してください。 編集: HailDB は、おそらく MySQL と並行して実行すると機能しません。

これらはいずれも MySQL と並行して実行でき (ライブで同じテーブルを使用)、C から使用できるため、要件を満たしていると思います。

MySQL Cluster を使用/移行できる場合は 、直接 API であるNDB APIおよびmemcache API を使用して MySQL Cluster にアクセスする方法であるndbmemcacheも参照してください。

異なるアプローチの意味は非常に異なるため、なぜこれをやろうとしているのかを知らずに答えるのは難しい.

于 2012-11-29T21:54:14.027 に答える
0

いいえ。C プログラム内から MySQL インデックスを利用して、MySQL エンジン以外の手段で MySQL インデックスにアクセスして、2 つの (a,b) ペア (キー) が同じかどうかをチェックする実用的な方法はありません。か否か。

MySQL エンジンの外部で MySQL データファイルにアクセスしたり、ユーザー定義関数を記述したりする必要のない、より実用的なソリューションがあります。


Q: mysql インデックスがファイル システムのどこに保存されているか知っていますか?

ファイル システム内のインデックスの場所は、テーブルのストレージ エンジンによって異なります。MyISAM エンジンの場合、インデックスは datadir/database ディレクトリの下の .MYI ファイルに保存されます。InnoDB インデックスは、InnoDB 管理テーブルスペース ファイル内に格納されます。テーブルが作成されたときに innodb_file_per_table 変数が設定されていた場合、innodb_data_home_dir/database サブディレクトリの下にテーブルごとに個別の .ibd ファイルが存在します。

Q:フォーマットはわかりますか?

各ストレージ エンジンのストレージ フォーマットは、MyISAM、InnoDB などと異なり、バージョンによっても異なります。MySQL がストレージ エンジンに必要とするものに関して、データがどのように保存されるかについてある程度の知識があります。内部に関する詳細情報は、各エンジンに固有のものです。

Q:実用的でない理由は何ですか?

非常に多くの作業が必要なため、実用的ではありません。また、将来変更される可能性のあるストレージ エンジンの詳細に依存することになります。問題空間を定義し、必要なものを返す SQL ステートメントを作成する方がはるかに実用的です。

あなたの質問に対するコメントで Quassnoi が指摘したように、UDF を作成したり、MySQL の外部から MySQL インデックスにアクセスしたりすることによって、どの特定の問題を解決しようとしているのかはまったく明確ではありません。私は、Quassnoi が効率的な SQL ステートメントで必要なことを達成するための良い方法を持っていると確信しています。

于 2012-11-29T23:06:26.967 に答える