3

私が扱っていること:

ActiveCollab 2を使用するプロジェクトがあり、データベース構造は私にとって新しいものです。実際には、すべてがproject_objectsテーブルに格納され、再帰的に階層関係にあります。

  • レコード1234は123のtype「チケット」である可能性がありますparent_id
  • レコード123は12のtype「カテゴリ」である可能性がありますparent_id
  • typeレコード12は「マイルストーン」などである可能性があります。

現在、このテーブルには450,000以上のレコードがあり、コード内のクエリの多くはname、インデックスがないフィールドを参照しています。値の例はDesignまたはDevelopmentです。

これはクエリの例です。

SELECT * FROM project_objects WHERE type = "Ticket" and name = "Design"

私の問題:

name12〜15秒以上かかるクエリがありますが、その列からのインデックスがなく、全文検索が必要だと感じてい ます。インデックスについての私の理解は、nameフィールドにインデックスを追加すると、読み取りは高速化されますが、挿入と更新は遅くなるということです。レコードが追加または更新されるたびにインデックスを完全に再構築する必要がありますか、それとも単に変更/追加されただけですか?より高速な書き込みに依存するコードベースの他の部分の速度を大幅に低下させることを意味する場合は、このクエリをインデックスで最適化したくありません。

私の質問:

1日あたり100回の読み取りと100回の書き込みを想定します。これは、MySQLのプロセスが高速である可能性が高くなります。インデックスなしで上記のテーブルに対して上記のクエリを実行するか、レコードが追加されるたびにインデックスを再構築する必要がありますか?

私にはベンチマークの実行を開始するための知識や権限がありませんが、完全に初心者に聞こえることなく、クライアントに提案を提供したいと思います。ありがとう!

編集:ここに表があります:

'CREATE TABLE `project_objects` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `source` varchar(50) DEFAULT NULL,
  `type` varchar(30) NOT NULL DEFAULT ''ProjectObject'',
  `module` varchar(30) NOT NULL DEFAULT ''system'',
  `project_id` int(10) unsigned NOT NULL DEFAULT ''0'',
  `milestone_id` int(10) unsigned DEFAULT NULL,
  `parent_id` int(10) unsigned DEFAULT NULL,
  `parent_type` varchar(30) DEFAULT NULL,
  `name` varchar(150) DEFAULT NULL,
  `body` longtext,
  `tags` text,
  `state` tinyint(4) NOT NULL DEFAULT ''0'',
  `visibility` tinyint(4) NOT NULL DEFAULT ''0'',
  `priority` tinyint(4) DEFAULT NULL,
  `created_on` datetime DEFAULT NULL,
  `created_by_id` smallint(5) unsigned NOT NULL DEFAULT ''0'',
  `created_by_name` varchar(100) DEFAULT NULL,
  `created_by_email` varchar(100) DEFAULT NULL,
  `updated_on` datetime DEFAULT NULL,
  `updated_by_id` smallint(5) unsigned DEFAULT NULL,
  `updated_by_name` varchar(100) DEFAULT NULL,
  `updated_by_email` varchar(100) DEFAULT NULL,
  `due_on` date DEFAULT NULL,
  `completed_on` datetime DEFAULT NULL,
  `completed_by_id` smallint(5) unsigned DEFAULT NULL,
  `completed_by_name` varchar(100) DEFAULT NULL,
  `completed_by_email` varchar(100) DEFAULT NULL,
  `comments_count` smallint(5) unsigned DEFAULT NULL,
  `has_time` tinyint(1) unsigned NOT NULL DEFAULT ''0'',
  `is_locked` tinyint(3) unsigned DEFAULT NULL,
  `estimate` float(9,2) DEFAULT NULL,
  `start_on` date DEFAULT NULL,
  `start_on_text` varchar(50) DEFAULT NULL,
  `due_on_text` varchar(50) DEFAULT NULL,
  `workflow_status` int(4) DEFAULT NULL,
  `varchar_field_1` varchar(255) DEFAULT NULL,
  `varchar_field_2` varchar(255) DEFAULT NULL,
  `integer_field_1` int(11) DEFAULT NULL,
  `integer_field_2` int(11) DEFAULT NULL,
  `float_field_1` double(10,2) DEFAULT NULL,
  `float_field_2` double(10,2) DEFAULT NULL,
  `text_field_1` longtext,
  `text_field_2` longtext,
  `date_field_1` date DEFAULT NULL,
  `date_field_2` date DEFAULT NULL,
  `datetime_field_1` datetime DEFAULT NULL,
  `datetime_field_2` datetime DEFAULT NULL,
  `boolean_field_1` tinyint(1) unsigned DEFAULT NULL,
  `boolean_field_2` tinyint(1) unsigned DEFAULT NULL,
  `position` int(10) unsigned DEFAULT NULL,
  `version` int(10) unsigned NOT NULL DEFAULT ''0'',
  PRIMARY KEY (`id`),
  KEY `type` (`type`),
  KEY `module` (`module`),
  KEY `project_id` (`project_id`),
  KEY `parent_id` (`parent_id`),
  KEY `created_on` (`created_on`),
  KEY `due_on` (`due_on`)
  KEY `milestone_id` (`milestone_id`)
) ENGINE=InnoDB AUTO_INCREMENT=993109 DEFAULT CHARSET=utf8'
4

2 に答える 2

2

列に 1 つのポイント インデックスを追加するための挿入コストは、nameほとんどの場合無視できます。おそらく数ミリ秒以内の一定の時間の増加に相当します。余分なディスク容量を消費しますが、通常は問題ありません。一部のパフォーマンスで経験している数秒のようなものはありません。

インデックスを追加して、パフォーマンスの向上をお楽しみください。

ところで:インデックスはすべての挿入で「再構築」されるわけではありません。それらは通常 B ツリーに実装されており、頻繁に削除しない限り、いくつかのレベルよりも大きくなると、再調整はほとんど必要ありません (深さの少ない再調整はかなり安価です)。

于 2013-01-21T18:04:22.940 に答える
2

@Ray が指摘しているように、Insert、Update、または Delete 操作ごとにインデックスを再構築する必要はありません。したがって、この (または同様の) クエリの効率を改善したいだけなら、 on(name, type)または on にインデックスを追加します(type, name)

すでに(type)単独でインデックスを持っているので、最初のインデックスを追加します:

ALTER TABLE project_objects 
  ADD INDEX name_type_IDX
    (name, type) ;

ビジーなサーバーでは数秒かかる場合がありますが、一度実行する必要があり、その後、あなたのような条件を持つすべてのクエリが恩恵を受けます. またはとnameのみを含む他のいくつかのタイプのクエリの効率も向上する可能性があります。nametype

WHERE name = 'Design' AND type = 'Ticket'      --- your query

WHERE name = 'Design'                          --- condition on `name` only 

GROUP BY name                                  --- group by  `name`

WHERE name LIKE 'Design%'                      --- range condition on `name` only

WHERE name = 'Design'                          --- equality condition on `name`
  AND type LIKE 'Ticket%'                      --- and range condition on `type`

WHERE name = 'Design'                          --- equality condition on `name`
GROUP BY type                                  --- and group by `type`

GROUP BY name                                  --- group by  `name`
       , type                                  --- and  `type`
于 2013-01-21T20:47:56.367 に答える