Có ngược lại thiết kế thực sự truyền thông giữa máy khách và máy chủ tôi có thể tiết lộ rằng DatabaseMetaData.getColumns của Oracle() phương pháp gửi các truy vấn SQL sau đây (mặc dù điều này có thể thay đổi với phiên bản ODBC driver và cài đặt):
declare
in_owner varchar2(128);
in_name varchar2(128);
in_column varchar2(128);
xyzzy SYS_REFCURSOR;
begin
in_owner := :1; // Which resolves to the schema (user) name supplied
in_name := :2; // Which resolves to the table name supplied
in_column := :3; // Which gets set to '%';
open xyzzy for
SELECT NULL AS table_cat,
t.owner AS table_schem,
t.table_name AS table_name,
t.column_name AS column_name,
DECODE( (SELECT a.typecode
FROM ALL_TYPES A
WHERE a.type_name = t.data_type),
'OBJECT', 2002,
'COLLECTION', 2003,
DECODE(substr(t.data_type, 1, 9),
'TIMESTAMP',
DECODE(substr(t.data_type, 10, 1),
'(',
DECODE(substr(t.data_type, 19, 5),
'LOCAL', -102, 'TIME ', -101, 93),
DECODE(substr(t.data_type, 16, 5),
'LOCAL', -102, 'TIME ', -101, 93)),
'INTERVAL ',
DECODE(substr(t.data_type, 10, 3),
'DAY', -104, 'YEA', -103),
DECODE(t.data_type,
'BINARY_DOUBLE', 101,
'BINARY_FLOAT', 100,
'BFILE', -13,
'BLOB', 2004,
'CHAR', 1,
'CLOB', 2005,
'COLLECTION', 2003,
'DATE', 93,
'FLOAT', 6,
'LONG', -1,
'LONG RAW', -4,
'NCHAR', -15,
'NCLOB', 2011,
'NUMBER', 2,
'NVARCHAR', -9,
'NVARCHAR2', -9,
'OBJECT', 2002,
'OPAQUE/XMLTYPE', 2009,
'RAW', -3,
'REF', 2006,
'ROWID', -8,
'SQLXML', 2009,
'UROWI', -8,
'VARCHAR2', 12,
'VARRAY', 2003,
'XMLTYPE', 2009,
1111)))
AS data_type,
t.data_type AS type_name,
DECODE (t.data_precision, null,
DECODE(t.data_type, 'NUMBER',
DECODE(t.data_scale, null, 0 , 38),
DECODE (t.data_type, 'CHAR', t.char_length, 'VARCHAR', t.char_length, 'VARCHAR2', t.char_length, 'NVARCHAR2', t.char_length, 'NCHAR', t.char_length, 'NUMBER', 0, t.data_length)), t.data_precision)
AS column_size,
0 AS buffer_length,
DECODE (t.data_type, 'NUMBER', DECODE(t.data_precision, null, DECODE(t.data_scale, null, -127 , t.data_scale), t.data_scale), t.data_scale) AS decimal_digits,
10 AS num_prec_radix,
DECODE (t.nullable, 'N', 0, 1) AS nullable,
NULL AS remarks,
t.data_default AS column_def,
0 AS sql_data_type,
0 AS sql_datetime_sub,
t.data_length AS char_octet_length,
t.column_id AS ordinal_position,
DECODE (t.nullable, 'N', 'NO', 'YES') AS is_nullable,
null as SCOPE_CATALOG,
null as SCOPE_SCHEMA,
null as SCOPE_TABLE,
null as SOURCE_DATA_TYPE,
'NO' as IS_AUTOINCREMENT,
t.virtual_column as IS_GENERATEDCOLUMN
FROM all_tab_cols t
WHERE t.owner LIKE in_owner ESCAPE '/'
AND t.table_name LIKE in_name ESCAPE '/'
AND t.column_name LIKE in_column ESCAPE '/'
AND t.user_generated = 'YES'
ORDER BY table_schem, table_name, ordinal_position;
end;
Bạn có thể đánh giá cao lý do tại sao có thể hơi chậm, đặc biệt là các bảng ALL_TAB_COLS và ALL_TYPES mỗi bảng có thể dài 1000 bản ghi. Tuy nhiên, trong khi Oracle đấu tranh để thực hiện lời gọi đầu tiên (phút), các cuộc gọi tiếp theo trả về kết quả gần như ngay lập tức. Đây là một vấn đề hiệu suất bảng-tham gia cổ điển mà mặc dù một tập hợp con dữ liệu được yêu cầu động cơ tham gia toàn bộ tập dữ liệu trước khi tính toán và phân phối tập hợp con được yêu cầu. Sau đó dữ liệu/kết quả bộ nhớ đệm hoạt động để cải thiện hiệu suất của các truy vấn tiếp theo.
Giải pháp tốt hơn có thể là sử dụng get_ddl() và phân tích cú pháp định nghĩa bảng trả lại theo this thread.
Ngoài ra bạn có thể truy vấn các siêu dữ liệu vào một bảng nhanh hơn bằng cách thực hiện một truy vấn giả sau đó sử dụng ResultSetMetaData như sau (Lưu ý: nhận xét cột siêu dữ liệu có thể không có ngay lập tức):
ResultSet rs = connection.CreateStatement.executeQuery("SELECT * from MyTable WHERE 1=0");
ResultSetMetaData md = rs.getMetaData();
for (int ix = 1; ix <= md.getColumnCount(); ix++)
{
int colSize = md.getPrecision(ix);
String nativeType = md.getColumnTypeName(ix);
int jdbcType = md.getColumnType(ix);
// and so on....
}
Bạn chắc chắn đó là lỗi của Springs? Bạn có thể chạy cùng một truy vấn bằng cách sử dụng JDBC đơn giản hoặc có thể trực tiếp trong bảng điều khiển cơ sở dữ liệu không? –
Tôi không nghĩ đó là lỗi của lò xo. Vấn đề là, nó không phải là một truy vấn cho mỗi se. Trình điều khiển JDBC giấu truy vấn thực sự thông qua phương thức 'getColumns()', vì vậy tôi không thể thấy điều gì đang thực sự xảy ra. –
@FranzKafka - Bạn có thể theo dõi SQL mà Spring tạo để xác định chính xác (các) bảng từ điển dữ liệu nào đang được truy vấn không? Thống kê có được thu thập trên từ điển dữ liệu không? –