22
Глава 1.
Оценка
Я сгенерировал для этого примера таблицу транзакций из двух милли-
онов строк и использовал некий абстрактный код Java™/JDBC, что-
бы показать, как различные способы написания кода могут повлиять
на производительность . Код на языке Java является упрощенным, так
что каждый, кто знает какой-нибудь язык программирования, сможет
понять суть .
Предположим, базовая часть приложения выглядит следующим обра-
зом (в арифметике дат в нижеприведенном коде используется синтак-
сис MySQL) . Эту программу я назвал
FirstExample.java:
1 try {
2
long txid;
3 long accountid;
4
float amount;
5 String curr;
6 float conv_amount;
7
8 PreparedStatement st1 = con.prepareStatement("select accountid"
9 + " from area_accounts"
10 + " where areaid = ?");
11 ResultSet rs1;
12 PreparedStatement st2 = con.prepareStatement("select txid,amount,curr"
13 + " from transactions"
14 + " where accountid=?"
15 + " and txdate >= date_sub(?, interval 30 day)"
16 + " order by txdate");
17 ResultSet rs2 = null;
18 PreparedStatement st3 = con.prepareStatement("insert into check_log(txid,"
19 + " conv_amount)"
20 + " values(?,?)");
21
22 st1.setInt(1, areaid);
23 rs1 = st1.executeQuery();
24 while (rs1.next()) {
25 accountid = rs1.getLong(1);
26 st2.setLong(1, accountid);
27 st2.setDate(2, somedate);
28 rs2 = st2.executeQuery();
29 while (rs2.next()) {
30 txid = rs2.getLong(1);
31 amount = rs2.getFloat(2);
32 curr = rs2.getString(3);
33 if (AboveThreshold(amount, curr)) {
34 // Конвертация
35 conv_amount = Convert(amount, curr, valuationdate);
36 st3.setLong(1, txid);
37 st3.setFloat(2, conv_amount);
38 dummy = st3.executeUpdate();
39 }
40 }
41 }
42 rs1.close();
43 st1.close();
Простой
пример
23
44 if (rs2 != null) {
45 rs2.close();
46 }
47 st2.close();
48 st3.close();
49 } catch(SQLException ex){
50 System.err.println("==> SQLException: ");
51 while (ex != null) {
52 System.out.println("Message: " + ex.getMessage ());
53 System.out.println("SQLState: " + ex.getSQLState ());
54 System.out.println("ErrorCode: " + ex.getErrorCode ());
55 ex = ex.getNextException();
56 System.out.println("");
57 }
58 }
Этот фрагмент напоминает тот код, который используется в реальных
приложениях . Небольшое пояснение по JDBC:
• У нас есть три оператора SQL (строки 8, 12 и 18), которые являют-
ся подготовленными операторами . Использование подготовленных
операторов – это правильный способ работы с JDBC, когда мы мно-
гократно исполняем идентичные операторы,
отличающиеся лишь
некоторыми значениями при каждом вызове (о подготовленных
операторах я буду говорить подробнее во второй главе) . Эти значе-
ния
представлены знаками вопроса, вместо которых при каждом
вызове будут подставлены конкретные величины с помощью функ-
ций setInt() в строке 22 или setLong() и setDate() в строках 26 и 27 .
• В строке 22 я установил значение (areaid),
которое я определил
и инициализировал в той части кода, которая здесь не показана .
• После того как шаблоны подстановки привязаны к реальным значе-
ниям, я могу вызвать функцию executeQuery(), как в строке 23, если
оператором SQL является select, или функцию executeUpdate(), как
в строке 38, если используется любой другой оператор . Для операто-
ров select я получаю результирующий набор, из которого могу в ци-
кле
извлечь все значения, например как в строках 30, 31 и 32 .
В коде есть два вызова служебных функций: AboveThreshold() в строке 33
проверяет, не превышает ли сумма предел для данной валюты, а Con-
vert()
в строке 35 преобразует сумму, превышающую предел, в валюту
отчета . Вот код этих двух функций:
private static boolean AboveThreshold(float amount,
String iso) throws Exception {
PreparedStatement thresholdstmt = con.prepareStatement("select threshold"
+ " from thresholds"
+ " where iso=?");
ResultSet rs;
boolean returnval = false;
thresholdstmt.setString(1, iso);