2

大量のデータペアを保存する必要があります。データ ペアの形式は次のとおりです。

パラメータ = 値

コンテナに関連しています。これは INI ファイルに似ています。たとえば、次の値を持つコンテナーがあります。

p1 = 32
p2 = "hello world"
p3 = -54

および別のものは次のとおりです。

p1 = 32
p2 = 36
p5 = 42
p6 = "bye"

コンテナーごとに定義されていない数のパラメーターがあります。値は任意の長さの数値または文字列です (数値は文字列に変換できます)。データの取得は、パラメーター名 ( 「すべての p1 値」 ) または値 ( 「値 'bye' を持つ 'p6' パラメーター」 ) によって行われます。データベースには何百万ものペアが含まれます。挿入と読み取りは非常に頻繁に行われ、レコードを削除または更新することはめったにありません。

私の最初の試みは、2 つのテーブルを作成することです。このような最初のもの:

CREATE TABLE IF NOT EXISTS `container` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  OTHER CONTAINER INFO
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;

whereidは、ペアを含む別のテーブルで使用されます。

CREATE TABLE IF NOT EXISTS `data` (
  `container` int(11) NOT NULL,
  `name` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
  `value` text COLLATE utf8_unicode_ci NOT NULL,
  KEY `container` (`container`),
  KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

データの追加:

INSERT INTO `container` (`id`) VALUES ('1'), ('2');
INSERT INTO  `data` (`container`, `name`, `value`) VALUES 
     ('1',  'p1',  '32'), 
     ('1',  'p2',  'hello world'), 
     ('1',  'p3',  '-54'), 
     ('2',  'p1',  '32'), 
     ('2',  'p2',  '36'), 
     ('2',  'p5',  '42'), 
     ('2',  'p6',  'bye');

動作しますが、あまり「使いやすく」高速ではありません。たとえば、各コンテナーからすべてのパラメーターを検索する必要がある場合p1=32、最初に 2 つの SQL クエリを作成する必要があります。

SELECT id FROM  `container` WHERE id IN (
   SELECT container
   FROM DATA WHERE name =  'p1'
  AND value =  '32')

次に、コンテナごとidにすべてのデータを取得します。

SELECT * FROM  `data` WHERE container = '$id'

次のようなテーブルが返されるため、PHP を介して後処理を行います。

container   name    value
    1       p1      32
    1       p2      hello world
    1       p3      -54

(後処理は array_* 関数を数回呼び出すだけですが、処理が遅くなります)。

50000 のデータ ペアを含むデータベースでテストしており、この手順を使用してすべてのレコードを一覧表示するには 5 秒以上かかります。問題は、この種のデータをどのように保存するかです。または実装のパフォーマンスを向上させる方法は?

: 問題は、最初の SQL クエリ (0'003 秒) や 2 番目の SQL クエリ (それぞれ 0'002 秒) ではありません。問題は、最初の SQL 文の結果ごとに SQL クエリを作成することです!!

注 2 : 目標は、各結果を含む PHP 配列と、各結果に対してキーと値のペアを含む連想配列を作成することです。の結果print_r:

Array
(
    [1] => Array
        (
            [p1] => 32
            [p2] => hello world
            [p3] => -54
        )
    [2] => Array
        (
            [p1] => 32
            [p2] => 36
            [p5] => 42
            [p6] => bye
        )
)

そしてもちろん、ここに示したデータ構造は私の最初の試みであり、研究中です。

4

4 に答える 4

2

2 つの個別のクエリは必要ありません。結合はそこで正常に機能します。サブセレクトも必要ありません。2 つのクエリは次のようになります。

SELECT id FROM  `container` c 
JOIN data d ON c.id = d.container
d.name =  'p1'
AND d.value =  '32';

わかりました、あなたのメモを見ました。すべてのデータを同じ行に入れますか? 私はこのクエリを使用しませんが、これらはあなたが望む結果ですか?

SELECT id, GROUP_CONCAT(CONCAT_WS("=", d.name, d.value)) results FROM  `container` c 
JOIN data d ON c.id = d.container
HAVING LOCATE("p1=32", results) > 0;
于 2012-10-17T10:00:37.527 に答える
1

コンテナーごとのすべての結果を 1 行に表示する場合は、おそらくピボット テーブルを使用する必要があります。ただし、可変数の data.name 値を取得する可能性があることを考えると、単一の単純なクエリでこれを行うことはできません。SQL を動的に生成するには、proc を作成する必要があります。

このリンクが役に立ちます: http://www.artfulsoftware.com/infotree/queries.php#78

結果の SQL は次のようになります (未テスト)

SELECT 
  c.id, 
  GROUP_CONCAT(if(d.name = 'p1', d.value, NULL)) AS 'p1', 
  GROUP_CONCAT(if(d.name = 'p2', d.value, NULL)) AS 'p2', 
  GROUP_CONCAT(if(d.name = 'p3', d.value, NULL)) AS 'p3', 
  GROUP_CONCAT(if(d.name = 'p4', d.value, NULL)) AS 'p4', 
  GROUP_CONCAT(if(d.name = 'p5', d.value, NULL)) AS 'p5', 
  GROUP_CONCAT(if(d.name = 'p6', d.value, NULL)) AS 'p6', 
FROM container c
JOIN data d ON c.id = d.container
GROUP BY c.id; 

次のような結果が得られます。

|id    |p1    |p2            |p3    |p4    |p5   |p6  | 
-------------------------------------------------------
|1     |32    |hello world   |-54   |      |     |    |
|2     |32    |36            |      |      |42   |bye |
于 2012-10-17T10:49:25.523 に答える
0

これを試して:

SELECT 
   container.id 
FROM 
   `container` 
LEFT JOIN `DATA`
   ON container.ID = DATA.container
WHERE DATA.name =  'p1'
   AND DATA.value =  '32'
于 2012-10-17T10:04:18.590 に答える