提交 ee86e638 authored 作者: Thomas Mueller's avatar Thomas Mueller

Documentation.

上级 e5e89883
......@@ -92,7 +92,7 @@ CALL 15*25
"
"Commands (DML)","EXPLAIN","
EXPLAIN { [ PLAN FOR ] | ANALYZE } { select | insert | update | delete }
EXPLAIN { [ PLAN FOR ] | ANALYZE } { select | insert | update | delete | merge }
","
Shows the execution plan for a statement.
When using EXPLAIN ANALYZE, the statement is actually executed, and the query plan
......
......@@ -18,7 +18,9 @@ Change Log
<h1>Change Log</h1>
<h2>Next Version (unreleased)</h2>
<ul><li>Issue 266: Domains: a NOT NULL clause in a domain definition ignored.
<ul><li>EXPLAIN SELECT didn't include the sample size if one was set.
</li><li>Improved EXPLAIN plan formatting and documentation.
</li><li>Issue 266: Domains: a NOT NULL clause in a domain definition ignored.
</li><li>More accurate calculation of variance and standard deviation for large number of samples with low variance
(now using Welford's method).
</li><li>Server: CLOB data with unicode characters between character code 0xd800 and 0xdfff
......
......@@ -20,14 +20,16 @@ Performance
Performance Comparison</a><br />
<a href="#poleposition_benchmark">
PolePosition Benchmark</a><br />
<a href="#application_profiling">
Application Profiling</a><br />
<a href="#database_profiling">
Database Profiling</a><br />
<a href="#database_performance_tuning">
Database Performance Tuning</a><br />
<a href="#built_in_profiler">
Using the Built-In Profiler</a><br />
<a href="#application_profiling">
Application Profiling</a><br />
<a href="#database_profiling">
Database Profiling</a><br />
<a href="#explain_plan">
Statement Execution Plans</a><br />
<a href="#fast_import">
Fast Database Import</a><br />
......@@ -305,89 +307,6 @@ To change that, use the database URL <code>jdbc:h2:file:data/h2/dbbench;DB_CLOSE
Unfortunately, the PolePosition test does not take this into account.
</li></ul>
<h2 id="application_profiling">Application Profiling</h2>
<h3>Analyze First</h3>
<p>
Before trying to optimize performance, it is important to understand where the problem is (what part of the application is slow).
Blind optimization or optimization based on guesses should be avoided, because usually it is not an efficient strategy.
There are various ways to analyze an application. Sometimes two implementations can be compared using
<code>System.currentTimeMillis()</code>. But this does not work for complex applications with many modules, and for memory problems.
</p>
<p>
A simple way to profile an application is to use the built-in profiling tool of java. Example:
</p>
<pre>
java -Xrunhprof:cpu=samples,depth=16 com.acme.Test
</pre>
<p>
Unfortunately, it is only possible to profile the application from start to end. Another solution is to create
a number of full thread dumps. To do that, first run <code>jps -l</code> to get the process id, and then
run <code>jstack &lt;pid&gt;</code> or <code>kill -QUIT &lt;pid&gt;</code> (Linux) or press
Ctrl+C (Windows).
</p>
<p>
A simple profiling tool is included in H2. To use it, the application needs to be changed slightly. Example:
</p>
<pre>
import org.h2.util;
...
profiler = new Profiler();
profiler.startCollecting();
// application code
profiler.stopCollecting();
System.out.println(profiler.getTop(3));
</pre>
<p>
The profiler is built into the H2 Console tool, to analyze databases that open slowly.
To use it, run the H2 Console, and then click on 'Test Connection'.
Afterwards, click on "Test successful" and you get the most common stack traces,
which helps to find out why it took so long to connect. You will only get the stack traces
if opening the database took more than a few seconds.
</p>
<h2 id="database_profiling">Database Profiling</h2>
<p>
The <code>ConvertTraceFile</code> tool generates SQL statement statistics at the end of the SQL script file.
The format used is similar to the profiling data generated when using <code>java -Xrunhprof</code>.
For this to work, the trace level needs to be 2 or higher (<code>TRACE_LEVEL_FILE=2</code>).
The easiest way to set the trace level is to append the setting to the database URL, for example:
<code>jdbc:h2:~/test;TRACE_LEVEL_FILE=2</code> or <code>jdbc:h2:tcp://localhost/~/test;TRACE_LEVEL_FILE=2</code>.
As an example, execute the the following script using the H2 Console:
</p>
<pre>
SET TRACE_LEVEL_FILE 2;
DROP TABLE IF EXISTS TEST;
CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255));
@LOOP 1000 INSERT INTO TEST VALUES(?, ?);
SET TRACE_LEVEL_FILE 0;
</pre>
<p>
After running the test case, convert the <code>.trace.db</code> file using the <code>ConvertTraceFile</code> tool.
The trace file is located in the same directory as the database file.
</p>
<pre>
java -cp h2*.jar org.h2.tools.ConvertTraceFile
-traceFile "~/test.trace.db" -script "~/test.sql"
</pre>
<p>
The generated file <code>test.sql</code> will contain the SQL statements as well as the
following profiling data (results vary):
</p>
<pre>
-----------------------------------------
-- SQL Statement Statistics
-- time: total time in milliseconds (accumulated)
-- count: how many times the statement ran
-- result: total update count or row count
-----------------------------------------
-- self accu time count result sql
-- 62% 62% 158 1000 1000 INSERT INTO TEST VALUES(?, ?);
-- 37% 100% 93 1 0 CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255));
-- 0% 100% 0 1 0 DROP TABLE IF EXISTS TEST;
-- 0% 100% 0 1 0 SET TRACE_LEVEL_FILE 3;
</pre>
<h2 id="database_performance_tuning">Database Performance Tuning</h2>
<h3>Keep Connections Open or Use a Connection Pool</h3>
......@@ -607,6 +526,175 @@ prof.stopCollecting();
System.out.println(prof.getTop(3));
</pre>
<h2 id="application_profiling">Application Profiling</h2>
<h3>Analyze First</h3>
<p>
Before trying to optimize performance, it is important to understand where the problem is (what part of the application is slow).
Blind optimization or optimization based on guesses should be avoided, because usually it is not an efficient strategy.
There are various ways to analyze an application. Sometimes two implementations can be compared using
<code>System.currentTimeMillis()</code>. But this does not work for complex applications with many modules, and for memory problems.
</p>
<p>
A simple way to profile an application is to use the built-in profiling tool of java. Example:
</p>
<pre>
java -Xrunhprof:cpu=samples,depth=16 com.acme.Test
</pre>
<p>
Unfortunately, it is only possible to profile the application from start to end. Another solution is to create
a number of full thread dumps. To do that, first run <code>jps -l</code> to get the process id, and then
run <code>jstack &lt;pid&gt;</code> or <code>kill -QUIT &lt;pid&gt;</code> (Linux) or press
Ctrl+C (Windows).
</p>
<p>
A simple profiling tool is included in H2. To use it, the application needs to be changed slightly. Example:
</p>
<pre>
import org.h2.util;
...
profiler = new Profiler();
profiler.startCollecting();
// application code
profiler.stopCollecting();
System.out.println(profiler.getTop(3));
</pre>
<p>
The profiler is built into the H2 Console tool, to analyze databases that open slowly.
To use it, run the H2 Console, and then click on 'Test Connection'.
Afterwards, click on "Test successful" and you get the most common stack traces,
which helps to find out why it took so long to connect. You will only get the stack traces
if opening the database took more than a few seconds.
</p>
<h2 id="database_profiling">Database Profiling</h2>
<p>
The <code>ConvertTraceFile</code> tool generates SQL statement statistics at the end of the SQL script file.
The format used is similar to the profiling data generated when using <code>java -Xrunhprof</code>.
For this to work, the trace level needs to be 2 or higher (<code>TRACE_LEVEL_FILE=2</code>).
The easiest way to set the trace level is to append the setting to the database URL, for example:
<code>jdbc:h2:~/test;TRACE_LEVEL_FILE=2</code> or <code>jdbc:h2:tcp://localhost/~/test;TRACE_LEVEL_FILE=2</code>.
As an example, execute the the following script using the H2 Console:
</p>
<pre>
SET TRACE_LEVEL_FILE 2;
DROP TABLE IF EXISTS TEST;
CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255));
@LOOP 1000 INSERT INTO TEST VALUES(?, ?);
SET TRACE_LEVEL_FILE 0;
</pre>
<p>
After running the test case, convert the <code>.trace.db</code> file using the <code>ConvertTraceFile</code> tool.
The trace file is located in the same directory as the database file.
</p>
<pre>
java -cp h2*.jar org.h2.tools.ConvertTraceFile
-traceFile "~/test.trace.db" -script "~/test.sql"
</pre>
<p>
The generated file <code>test.sql</code> will contain the SQL statements as well as the
following profiling data (results vary):
</p>
<pre>
-----------------------------------------
-- SQL Statement Statistics
-- time: total time in milliseconds (accumulated)
-- count: how many times the statement ran
-- result: total update count or row count
-----------------------------------------
-- self accu time count result sql
-- 62% 62% 158 1000 1000 INSERT INTO TEST VALUES(?, ?);
-- 37% 100% 93 1 0 CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255));
-- 0% 100% 0 1 0 DROP TABLE IF EXISTS TEST;
-- 0% 100% 0 1 0 SET TRACE_LEVEL_FILE 3;
</pre>
<h2 id="explain_plan">Statement Execution Plans</h2>
<p>
The SQL statement <code>EXPLAIN</code> displays the indexes and optimizations the database uses for a statement.
The following statements support <code>EXPLAIN</code>: <code>SELECT, UPDATE, DELETE, MERGE, INSERT</code>.
The following query shows that the database uses the primary key index to search for rows:
</p>
<pre>
EXPLAIN SELECT * FROM TEST WHERE ID=1;
SELECT
TEST.ID,
TEST.NAME
FROM PUBLIC.TEST
/* PUBLIC.PRIMARY_KEY_2: ID = 1 */
WHERE ID = 1
</pre>
<p>
For joins, the tables in the execution plan are sorted in the order they are processed.
The following query shows the database first processes the table <code>INVOICE</code> (using the primary key).
For each row, it will additionally check that the value of the column <code>AMOUNT</code> is larger than zero,
and for those rows the database will search in the table <code>CUSTOMER</code> (using the primary key).
The query plan contains some redundancy so it is a valid statement.
</p>
<pre>
CREATE TABLE CUSTOMER(ID IDENTITY, NAME VARCHAR);
CREATE TABLE INVOICE(ID IDENTITY,
CUSTOMER_ID INT REFERENCES CUSTOMER(ID),
AMOUNT NUMBER);
EXPLAIN SELECT I.ID, C.NAME FROM CUSTOMER C, INVOICE I
WHERE I.ID=10 AND AMOUNT>0 AND C.ID=I.CUSTOMER_ID;
SELECT
I.ID,
C.NAME
FROM PUBLIC.INVOICE I
/* PUBLIC.PRIMARY_KEY_9: ID = 10 */
/* WHERE (I.ID = 10)
AND (AMOUNT > 0)
*/
INNER JOIN PUBLIC.CUSTOMER C
/* PUBLIC.PRIMARY_KEY_5: ID = I.CUSTOMER_ID */
ON 1=1
WHERE (C.ID = I.CUSTOMER_ID)
AND ((I.ID = 10)
AND (AMOUNT > 0))
</pre>
<h3>Displaying the Scan Count</h3>
<p>
<code>EXPLAIN ANALYZE</code> additionally shows the scanned rows per table and pages read from disk per table or index.
This will actually execute the query, unlike <code>EXPLAIN</code> which only prepares it.
The following query scanned 1000 rows, and to do that had to read 85 pages from the data area of the table.
Running the query twice will not list the pages read from disk, because they are now in the cache.
The <code>tableScan</code> means this query doesn't use an index.
</p>
<pre>
EXPLAIN ANALYZE SELECT * FROM TEST;
SELECT
TEST.ID,
TEST.NAME
FROM PUBLIC.TEST
/* PUBLIC.TEST.tableScan */
/* scanCount: 1000 */
/*
total: 85
TEST.TEST_DATA read: 85 (100%)
*/
</pre>
<h3>Special Optimizations</h3>
<p>
For certain queries, the database doesn't need to read all rows, or doesn't need to sort the result even if <code>ORDER BY</code> is used.
</p><p>
For queries of the form <code>SELECT COUNT(*), MIN(ID), MAX(ID) FROM TEST</code>, the query plan includes the line
<code>/* direct lookup */</code> if the data can be read from an index.
</p><p>
For queries of the form <code>SELECT DISTINCT CUSTOMER_ID FROM INVOICE</code>, the query plan includes the line
<code>/* distinct */</code> if there is an non-unique or multi-column index on this column, and if this column has a low selectivity.
</p><p>
For queries of the form <code>SELECT * FROM TEST ORDER BY ID</code>, the query plan includes the line
<code>/* index sorted */</code> to indicate there is no separate sorting required.
</p><p>
For queries of the form <code>SELECT * FROM TEST GROUP BY ID ORDER BY ID</code>, the query plan includes the line
<code>/* group sorted */</code> to indicate there is no separate sorting required.
</p>
<h2 id="fast_import">Fast Database Import</h2>
<p>
To speed up large imports, consider using the following options temporarily:
......
......@@ -254,6 +254,7 @@ See also <a href="build.html#providing_patches">Providing Patches</a>.
</li><li>Oracle: support DECODE method (convert to CASE WHEN).
</li><li>Native search: support "phrase search", wildcard search (* and ?), case-insensitive search, boolean operators, and grouping
</li><li>Improve documentation of access rights
</li><li>Support opening a database that is in the classpath, maybe using a new file system. Workaround: detect jar file using getClass().getProtectionDomain().getCodeSource().getLocation().
</li><li>Support ENUM data type (see MySQL, PostgreSQL, MS SQL Server, maybe others)
</li><li>Remember the user defined data type (domain) of a column
</li><li>MVCC: support multi-threaded kernel with multi-version concurrency.
......@@ -290,7 +291,6 @@ See also <a href="build.html#providing_patches">Providing Patches</a>.
</li><li>MySQL compatibility: real SQL statement for DESCRIBE TEST
</li><li>Use a default delay of 1 second before closing a database.
</li><li>Write (log) to system table before adding to internal data structures.
</li><li>Support opening a database that is in the classpath, maybe using a new file system.
</li><li>Doclet (javadocs): constructors are not listed.
</li><li>Support direct lookup for MIN and MAX when using WHERE (see todo.txt / Direct Lookup).
</li><li>Support other array types (String[], double[]) in PreparedStatement.setObject(int, Object);
......
......@@ -540,7 +540,7 @@ Shutting down a TCP server can be protected using the option <code>-tcpPassword<
This database supports Hibernate version 3.1 and newer. You can use the HSQLDB Dialect,
or the native H2 Dialect. Unfortunately the H2 Dialect included in some old versions of Hibernate was buggy.
A <a href="http://opensource.atlassian.com/projects/hibernate/browse/HHH-3401">patch
for Hibernate</a> has been submitted and is now applied.
for Hibernate</a> has been submitted and is now applied.
You can rename it to <code>H2Dialect.java</code> and include this as a patch in your application,
or upgrade to a version of Hibernate where this is fixed.
</p>
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -36,7 +36,7 @@ CALL expression
","
Calculates a simple expression."
"Commands (DML)","EXPLAIN","
EXPLAIN { [ PLAN FOR ] | ANALYZE } { select | insert | update | delete }
EXPLAIN { [ PLAN FOR ] | ANALYZE } { select | insert | update | delete | merge }
","
Shows the execution plan for a statement."
"Commands (DML)","MERGE","
......
......@@ -1119,6 +1119,12 @@ public class Data {
}
}
/**
* Copy a String from a reader to an output stream.
*
* @param source the reader
* @param target the output stream
*/
public static void copyString(Reader source, OutputStream target) throws IOException {
char[] buff = new char[Constants.IO_BUFFER_SIZE];
Data d = new Data(null, new byte[3 * Constants.IO_BUFFER_SIZE]);
......
......@@ -661,7 +661,8 @@ pyankov enctype multipart boundary mistake enlarge demonstrates aggregating
bypassing khtml doubled inlined defragmented registers leftover ugly artificially
presentation defragment queried activities knut tailored dhis statistical norway
mailto dong adconion edong twitter consortium ogc geo geospatial flexibility
mbeans unregisters subtracting multiplying dividing contended bindings
mbeans unregisters subtracting multiplying dividing contended bindings
projection managing observer misuse windowed discriminator abort familiar rice
reachable mind develop disposition extras arithmetics readwrite syncable
requeried requery closable curr outdated
reachable mind develop disposition extras arithmetics readwrite syncable
requeried requery closable curr outdated market accurate borg theis welford
ooq exceeded eye
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论