Nano Hash - криптовалюты, майнинг, программирование

SQL: повышение эффективности COUNT (*) ›1

если вы хотите узнать, COUNT(*)> 0, вы можете использовать EXISTS, чтобы сделать запрос более эффективным. Есть ли способ сделать запрос более эффективным, если я хочу знать, COUNT(*)> 1?

(Должен быть совместим как с SQL Server, так и с Oracle.)

Спасибо, Джейми

Редактировать:

Я пытаюсь улучшить производительность некоторого кода. Есть несколько строк, похожих на:

if (SQL('SELECT COUNT(*) FROM table WHERE a = b') > 0) then...

и

if (SQL('SELECT COUNT(*) FROM table WHERE a = b') > 1) then...

В первой строке достаточно легко переключиться на оператор EXISTS, но могу ли я сделать вторую строку более эффективной? Из комментариев и моих собственных мыслей у меня есть следующие идеи, может ли какая-нибудь из них быть более эффективной?

if (SQLRecordCount('SELECT TOP 2 1 FROM table WHERE a = b') > 1) then...

(Я могу использовать ROWNUM для Oracle.)

if (SQL('SELECT 1 FROM table WHERE a = b HAVING COUNT(*) > 1') = 1) then...

Следующее не работает в SQL Server:

SELECT COUNT(*) FROM (SELECT TOP 2 FROM table WHERE a = b)

Но это касается Oracle:

SELECT COUNT(*) FROM (SELECT 1 FROM table WHERE a = b AND ROWNUM < 3)

Спасибо за вашу помощь.

10.02.2011

  • Я не уверен, что это только оптимизация для MySQL, но попробовали ли вы COUNT(primaryKeyField) > 1 ИЛИ COUNT(1) > 1, чтобы увидеть, лучше ли при этом используются индексы? 10.02.2011
  • @Ardman - Я предполагаю, что вопрос касается определенных мощностей, где, скажем, у вас есть 1000 строк на группу и вы можете остановить сканирование после первых двух совпадений аналогично тому, как EXISTS не нужно COUNT все совпадающие строки. 10.02.2011
  • Я могу думать о конкретных способах SQL Server с использованием TOP и CROSS APPLY. 10.02.2011
  • @Martin. Напишите и об этом :-) 10.02.2011
  • @pst - Готово. Я сделал это cw и, вероятно, удалю позже как несколько не по теме для этого вопроса ... 10.02.2011

Ответы:


1

Что-то вроде этого могло сработать:

select myDate
from myTable
where myColumn = myCondition
group by myDate
having count(*) > 1

Хотя, если бы у меня был ваш точный вопрос или разумное факсимиле, я мог бы помочь вам больше.

Поскольку фактическое ключевое слово более эффективно, насколько мне известно, вы как программист SQL мало что можете с этим поделать. Это будет функция того, насколько хорошо ваша СУБД обрабатывает фактический подсчет. Если он видит, что он вернет строку, если есть 2 вхождения, и перестает считать на 2, отлично. Если он недостаточно умен и отслеживает еще 1000 случаев, не так уж и хорошо.

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

10.02.2011
  • Я не думаю, что OP спрашивает о синтаксисе. Насколько я понимаю, они спрашивают, могут ли они избежать подсчета всех строк в группе, когда на самом деле им нужно только знать, есть ли более одной совпадающей строки. 10.02.2011
  • Я работаю в предположении, что OP не знает о ключевом слове HAVING, что разумно приводит к предположению, что они также не знают синтаксиса. Этот синтаксис предоставляет значениям более одной строки без предоставления фактического количества. Кроме того, как еще можно узнать, имеет ли значение более одного вхождения, не считая их где-то в процессе? 10.02.2011

  • 2

    Ваш вопрос на данный момент немного абстрактен. Не могли бы вы дать немного больше контекста?

    Я думаю, что если у вас есть составной индекс на foo, id, то приведенное ниже может быть выполнено двумя поисками индекса.

    SELECT CASE WHEN MAX(id)= MIN(id) THEN 0 ELSE 1 END
    FROM yourtable 
    WHERE foo='bar'
    

    Или, может быть, сделать план более явным

    SELECT CASE WHEN COUNT(*) = 2 THEN 1 ELSE 0 END FROM 
    (
        SELECT MAX(id)
        FROM yourtable 
        WHERE foo='bar'
        UNION
        SELECT MIN(id)
        FROM yourtable 
        WHERE foo='bar'
    ) AS T
    
    10.02.2011

    3

    Это не должно иметь большого значения, если он проиндексирован

    Пример:

    Таблица с 2 миллионами строк, довольно широкая, 900 МБ на диске, виртуальный SQL Server 2005.

    Это дает 17 876 строк

    SELECT COUNT(*), ThingID FROM dbo.TwoMillion IT GROUP BY ThingID HAVING COUNT(*) > 1
    
      |--Filter(WHERE:([Expr1002]>(1)))
           |--Compute Scalar(DEFINE:([Expr1002]=CONVERT_IMPLICIT(int,[Expr1005],0)))
                |--Hash Match(Aggregate, HASH:([IT].[ThingID]) DEFINE:([Expr1005]=COUNT(*)))
                     |--Index Scan(OBJECT:([MyDB].[dbo].[TwoMillion].[IX_Thing] AS [IT]))
    
    Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0
    Table 'TwoMillion'. Scan count 1, logical reads 8973, physical reads 3, read-ahead reads 8969... all zeroes
    

    На 2-м заходе

     Table 'Worktable'. = same
     Table 'TwoMillion'. Scan count 1, logical reads 8973, ... all zeroes
    
     CPU time = 453 ms,  elapsed time = 564 ms.
    
    10.02.2011
  • +1 Но ... это еще примерно полсекунды, если верить тому: - / Возможно, не рекорд, но и не то, что я считаю сверхбыстрым. 10.02.2011
  • @Pst: виртуальный сервер. x5 быстрее на физической коробке. И это широкий стол 10.02.2011

  • 4

    Полностью игнорируя требование перекрестной совместимости в SQL Server, вы можете использовать TOP для явного ограничения количества сканируемых строк. В некоторых сценариях это может быть полезно, как в приведенном ниже (несколько надуманном) примере.

    USE tempdb
    
    CREATE TABLE Orders
    (
    OrderId INT IDENTITY(1,1) PRIMARY KEY,
    Blah VARCHAR(10)
    )
    INSERT INTO Orders 
    SELECT TOP 10 LEFT(name,10)
    FROM sys.objects
    
    CREATE TABLE OrderItems
    (
    OrderItemId INT IDENTITY(1,1) PRIMARY KEY,
    OrderId INT REFERENCES Orders(OrderId)
    )
    CREATE NONCLUSTERED INDEX ix ON OrderItems(OrderId)
    
    INSERT INTO OrderItems (OrderId)
    SELECT TOP 1000000 1+ ROW_NUMBER() OVER (ORDER BY (SELECT 0))% 10 
    FROM sys.all_columns c1, sys.all_columns c2
    
    SET STATISTICS IO ON
    SET STATISTICS TIME ON
    
    SELECT o.OrderId, o.Blah
    FROM Orders o JOIN OrderItems oi ON o.OrderId = oi.OrderId
    GROUP BY o.OrderId, o.Blah
    HAVING COUNT(*) > 1
    
    /*
    Table 'Orders'. Scan count 0, logical reads 20
    Table 'OrderItems'. Scan count 1, logical reads 1742
    */
    
    
    SELECT o.OrderId, o.Blah
    FROM Orders o 
    CROSS APPLY 
    (SELECT TOP 2 OrderItemId FROM 
    OrderItems oi WHERE o.OrderId = oi.OrderId) CA
    GROUP BY o.OrderId, o.Blah
    HAVING COUNT(*) > 1
    
    /*
    Table 'OrderItems'. Scan count 10, logical reads 30
    Table 'Orders'. Scan count 1, logical reads 2
    */
    
    DROP TABLE OrderItems
    DROP TABLE Orders
    

    План выполнения

    10.02.2011

    5

    Я обнаружил, что следующая строка значительно повысила производительность SQL Server, увеличившись с 40 мс до 5 мс в моих тестах.

    SELECT COUNT(*) FROM (SELECT TOP 2 1 AS x FROM table Where a = b) AS y
    

    Обратите внимание на псевдонимы, они необходимы для работы запроса.

    К сожалению, следующий запрос, похоже, не улучшает производительность Oracle:

    SELECT COUNT(*) FROM table WHERE a = b AND ROWNUM < 3
    
    14.02.2011

    6

    Во-первых, вам не следует использовать звездочки, если вы хотите оптимизировать свои запросы.

    Может, лучше создать запрос с лимитом? Вас не интересует граф или что-то в этом роде. Вы только хотите знать, есть ли более одной записи:

    select id
    from mytable
    where ...
    limit 2
    

    Это должно быть очень быстро. Затем вызовите предоставленные вам countRows, чтобы получить нужный вам ответ.

    10.02.2011
  • звездочки в COUNT или EXISTS не имеют отношения к делу stackoverflow.com/questions/1221559/ count-vs-count1 / и stackoverflow.com/questions/3271455/ 10.02.2011
  • Я не сказал это для count (), я сказал, что он не должен это использовать. Если он использует звездочки в COUNT (), возможно, он использует звездочки в запросах SELECT. Поэтому я сказал ему избегать звездочек! И, как вы говорите, не будет различий в использовании звездочек в COUNT () или нет! Поэтому зачем вообще использовать звездочку? Вы можете полностью запретить его использование в своих sql-запросах, не нанеся вреда. 10.02.2011
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..