SQL, Выбирающий имена столбцов как значения

Это зависит, как реализованы исключения. Самый простой путь использует setjmp и longjmp. Это означает, что все регистры ЦП записаны в стек (который уже занимает время), и возможно некоторые другие данные должны быть созданы..., все это уже происходит в операторе попытки. Оператор броска должен раскрутить стек и восстановить значения всех регистров (и возможные другие значения в VM). Поэтому попытайтесь бросить, являются одинаково медленными, и это довольно медленно, однако если никакое исключение не выдается, выходить из блока попытки не занимает времени вообще в большинстве случаев (поскольку все помещается на стек, который моется автоматически, если метод существует).

Sun и другие распознали, что это является возможно субоптимальным, и конечно VMs становятся быстрее и быстрее за время. Существует другой способ реализовать исключения, который делает саму попытку молнией быстро (на самом деле, ничего не происходит для попытки вообще в целом - все, что должно произойти, уже сделан, когда класс загружается VM), и это делает бросок не совсем как медленный. Я не знаю, какая JVM использует эту новую, лучшую технику...

..., но Вы пишете в Java, таким образом, Ваш код позже только работает на одной JVM в одной определенной системе? С тех пор, если это может когда-либо работать на какой-либо другой платформе или какой-либо другой версии JVM (возможно какого-либо другого поставщика), кто говорит, они также используют внедрение FAST? Быстрый более сложен, чем медленный и не легко возможен во всех системах. Вы хотите остаться портативными? Тогда не полагайтесь на исключения, являющиеся быстрым.

Это также имеет большое значение, что Вы делаете в блоке попытки. Если Вы откроете блок попытки и никогда не называть метода из этого блока попытки, блок попытки будет крайний быстрый, поскольку JIT может тогда на самом деле рассматривать бросок как простой goto. Это ни не должно сохранять состояние стека, и при этом это не должно раскручивать стек, если исключение выдается (это только должно перейти к обработчикам выгод). Однако это не то, что Вы обычно делаете. Обычно Вы открываете блок попытки и затем называете метод, который мог бы выдать исключение, правильно? И даже если Вы просто используете блок попытки в рамках своего метода, каким методом это будет, который не называет никакой другой метод? Это просто вычислит число? Тогда, чему для Вас нужны исключения? Существуют намного более изящные способы отрегулировать процесс выполнения программы. Для в значительной степени чего-либо еще кроме простой математики, необходимо будет назвать внешний метод, и это уже уничтожает преимущество локального блока попытки.

Посмотрите следующий тестовый код:

public class Test {
    int value;


    public int getValue() {
        return value;
    }

    public void reset() {
        value = 0;
    }

    // Calculates without exception
    public void method1(int i) {
        value = ((value + i) / i) << 1;
        // Will never be true
        if ((i & 0xFFFFFFF) == 1000000000) {
            System.out.println("You'll never see this!");
        }
    }

    // Could in theory throw one, but never will
    public void method2(int i) throws Exception {
        value = ((value + i) / i) << 1;
        // Will never be true
        if ((i & 0xFFFFFFF) == 1000000000) {
            throw new Exception();
        }
    }

    // This one will regularly throw one
    public void method3(int i) throws Exception {
        value = ((value + i) / i) << 1;
        // i & 1 is equally fast to calculate as i & 0xFFFFFFF; it is both
        // an AND operation between two integers. The size of the number plays
        // no role. AND on 32 BIT always ANDs all 32 bits
        if ((i & 0x1) == 1) {
            throw new Exception();
        }
    }

    public static void main(String[] args) {
        int i;
        long l;
        Test t = new Test();

        l = System.currentTimeMillis();
        t.reset();
        for (i = 1; i < 100000000; i++) {
            t.method1(i);
        }
        l = System.currentTimeMillis() - l;
        System.out.println(
            "method1 took " + l + " ms, result was " + t.getValue()
        );

        l = System.currentTimeMillis();
        t.reset();
        for (i = 1; i < 100000000; i++) {
            try {
                t.method2(i);
            } catch (Exception e) {
                System.out.println("You'll never see this!");
            }
        }
        l = System.currentTimeMillis() - l;
        System.out.println(
            "method2 took " + l + " ms, result was " + t.getValue()
        );

        l = System.currentTimeMillis();
        t.reset();
        for (i = 1; i < 100000000; i++) {
            try {
                t.method3(i);
            } catch (Exception e) {
                // Do nothing here, as we will get here
            }
        }
        l = System.currentTimeMillis() - l;
        System.out.println(
            "method3 took " + l + " ms, result was " + t.getValue()
        );
    }
}

Результат:

method1 took 972 ms, result was 2
method2 took 1003 ms, result was 2
method3 took 66716 ms, result was 2

замедление от блока попытки является слишком маленьким для исключения факторов соединения, таких как фоновые процессы. Но блок выгоды уничтожил все и сделал его в 66 раз медленнее!

, Поскольку я сказал, результат не будет состоять в том, что плохо, если Вы помещаете попытку/выгоду и бросаете все в рамках того же метода (method3), но это - специальная оптимизация JIT, на которую я не положился бы. И даже когда с помощью этой оптимизации, бросок является все еще довольно медленным. Таким образом, я не знаю то, что Вы пытаетесь сделать здесь, но существует определенно лучший способ сделать его, чем использование попытки/выгоды/броска.

6
задан theringostarrs 9 August 2009 в 23:17
поделиться

2 ответа

Если у вас есть фиксированные столбцы, вы всегда можете сделать это:

SELECT period, 'Truck' AS NameOfVehicle, Truck AS Value FROM vehicle
UNION ALL
SELECT period, 'Car', Car FROM vehicle
UNION ALL
SELECT period, 'Boat', Boat FROM vehicle

Если столбцы являются динамическими или неизвестными, то это немного сложнее и будет зависеть от конкретных функций поставщика для запроса схемы и динамический оператор SQL.

10
ответ дан 8 December 2019 в 18:39
поделиться

Хотя запрос Cletus верен, стоит отметить, что вы можете использовать ключевое слово UNPIVOT в SQL Server 2005 и более поздних версиях, чтобы сделать почти то же самое:

  select
    period, nameOfVehicle, value
  from T unpivot (
    value for nameOfVehicle in ([Car],[Truck],[Boat])
  ) as U;

Разница между UNPIVOT и решением cletus состоит в том, что UNPIVOT не будет включать строки, для которых [значение] IS NULL. Если вам нужны значения NULL, вам придется проявить немного хитрости и использовать значение, которое никогда не может появиться в таблице (здесь я использую пустую строку):

with X(period,Car,Truck,Boat) as (
  select period,coalesce(Car,''),coalesce(Truck,''),coalesce(Boat,'')
  from T
)
  select
    period, nameOfVehicle, case when value = '' then null else value end as value
  from X unpivot (
    value for nameOfVehicle in ([Car],[Truck],[Boat])
  ) as U;

В зависимости от столбцов, которые вы сохраните после отмены поворота, это может другой вариант (это решение сохранит значения NULL):

select
  period,
  nameOfVehicle,
  max(case nameOfVehicle 
      when 'Truck' then Truck
      when 'Car' then Car
      when 'Boat' then Boat end) as value
  from T cross join (
  values ('Truck'),('Car'),('Boat')
) as Columns(nameOfVehicle)
group by period, nameOfVehicle;
3
ответ дан 8 December 2019 в 18:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: