診断

Confluence では、クエリが lower() 関数を使用するため、タイトルでページを取得する際にパフォーマンス上の問題が発生することがあります。クエリはたとえば次のようなものになります。

select * from CONTENT where lower(TITLE) = :title and SPACEID = :spaceid

データベース プロファイリングでは、実行に時間がかかる次のようなクエリが表示される場合があります(部分的に太字にしてあります)。 

select ... from CONTENT page0_, SPACES space1_
where page0_.CONTENTTYPE='PAGE'
and ((lower(space1_.SPACEKEY)= @P0 and page0_.SPACEID=space1_.SPACEID)
and(lower(page0_.TITLE)= @P1 )
and(page0_.PREVVER is null )and(page0_.CONTENT_STATUS='current' ))

Typically, databases don't use indexes when you use a function in a where clause; they do a table scan instead. This makes the performance of this query not ideal (CONF-11577).

一般的な解決策

多くのデータベース (たとえば Oracle、PostgreSQL、DB2 for z/OS)では、列名の代わりに関数を使用するだけで、通常の "create index" 構文を使用してインデックスを作成することが可能です。

create index CONFTITLE_LOWER on CONTENT(lower(TITLE));

ソース

SQL Server

SQL Server では、データベースのテーブルに計算列を追加して、その列にインデックスを追加できます。

alter table CONTENT add TITLE_LOWER as lower(TITLE);
create index CONFTITLE_LOWER on CONTENT(TITLE_LOWER);

ソース

MySQL

現在、MySQL では小文字のインデックスを作成することはできません。Confluence 3.0 には、このデータベースでのパフォーマンス上の問題を軽減するキャッシュの改善がいくつか含まれています。

ソース:

大文字と小文字を区別しない照合を使用する MySQL データベースの回避策

MySQL データベースが大文字と小文字を区別する照合または大文字と小文字を区別しない照合を使用するように設定されているかどうかを確認してください。データベースが大文字と小文字を区別しない照合に設定されているかどうかを確認するためのクエリは、以下のとおりです。

フィールド = 'title' のコンテンツから列全体を表示する
field = 'spacekey' のスペースから列全体を表示する

collation_name<encoding>_ci として返された場合、ci は大文字と小文字を区別しない照合を示します。

データベースが大文字と小文字を区別しない照合を使用するように設定されている場合は、<Confluence-Install>/confluence/WEB-INF/lib/confluence-2.x.x.jar/com/atlassian/confluence/core/ に存在する ContentEntityObject.hbm.xml ファイルで、次のクエリから lower を削除してみてください。

<query name="confluence.page_findLatestBySpaceKeyTitle"><![CDATA[
	from Page page
	where lower(page.space.key) = :spaceKey and
		lower(page.title) = :pageTitle and
		page.originalVersion is null and
		page.contentStatus = 'current'
]]></query>

<query name="confluence.page_findLatestBySpaceKeyTitleOptimisedForComments"><![CDATA[
	from Page page 
	left join fetch page.comments as theComments
	left join fetch theComments.children 
	where lower(page.space.key) = :spaceKey and
		lower(page.title) = :pageTitle and
		page.originalVersion is null and
		page.contentStatus = 'current'
]]></query>

DB2 for Linux, Unix or Windows

DB2 supports indexes on generated columns which are used for queries with a matching predicate. You can implement it like this:

ALTER TABLE CONTENT ADD COLUMN TITLE_LOWER GENERATED ALWAYS AS (LOWER(TITLE));
CREATE INDEX CONFTITLE_LOWER ON CONTENT(TITLE_LOWER)

関連ページ