SQL:按主键删除vs外键性能?

时间:2015-05-22 13:09:18

标签: sql sql-server sql-server-2008 tsql sqlperformance

想知道以下两个DELETE语句是否存在任何性能差异?:

按主键删除:

DELETE FROM dbo.Users WHERE Id IN (1,2,3,4,5)

通过某些外键删除:

DELETE FROM dbo.Users WHERE Email_Id IN (454,851,909)

假设我们正在讨论约3000万行dbo.Users表,而IN()子句包含约5-200K项。​​

是否有任何内置功能可以通过主键和其他字段进行删除?

2 个答案:

答案 0 :(得分:0)

如果对FK没有唯一约束,我会使用PK。它保证是每个ID的一个索引查找。 FK可能你有倍数,所以如果它存在(你应该),你将对FK索引进行扫描。

因为您有很多记录要删除,所以优化器可能会决定表扫描是最快的,所以无关紧要。

为了解决你的问题,关于是否有一些特殊功能可以更好地删除这种或那种方式,答案并非如此。选择是一回事,无论你如何选择记录,删除几乎都以相同的方式发生。截断表格有时可以更快地完成,但这不是你想要做的事情。

答案 1 :(得分:0)

我首先要优化选择
获取查询计划
如果你两个都做,它甚至会告诉你相对成本
我怀疑删除部分会比那里花费更长的时间,因此无关紧要

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.StringTokenizer;

public class FileReaderExample
{
        private Person person;

        private Person readFile()
        {
          File file = new File("d:\\text.txt");
          try
          {
            FileReader fileReader = new FileReader(file);
            BufferedReader br = new BufferedReader(fileReader);
            String line;
            while ((line = br.readLine()) != null)
            {
              line = line.trim();
              StringTokenizer st = new StringTokenizer(line);
              if ( line.endsWith("gender: f") )
              {
                person = new Female();
                st.nextToken();
                String name = st.nextToken();
                person.setName(name);
              }
              else if ( line.endsWith("gender: m") )
              {
                person = new Male();
                st.nextToken();
                String name = st.nextToken();
                person.setName(name);
              }
              else if ( line.startsWith("age:") )
              {
                st.nextToken();
                String age = st.nextToken();
                person.setAge(age);
                line = br.readLine();
              }
            }

          }
          catch (IOException io)
          {
            // 
          }

          return person;
        }

      public abstract class Person
      {
        private String name;
        private String age;
        private String grade;

        public String getAge()
        {
          return age;
        }

        public void setAge(String age)
        {
          this.age = age;
        }

        public String getName()
        {
          return name;
        }

        public void setName(String name)
        {
          this.name = name;
        }

        public String getGrade()
        {
          return grade;
        }

        public void setGrade(String grade)
        {
          this.grade = grade;
        }

      }

      public class Female extends Person
      {
         public Female() {}
      }


      public class Male extends Person
      {
         public Male() {}
      }

如果你有一个大的IN,你可能想要将其分解以包含事务日志

在一个非常大的删除中你甚至可以更好地禁用表上的索引,然后重建它们。禁用每个索引但PK并通过PK删除并重建索引。